Bagaimana cara mengubah Koleksi ke Daftar?

294

Saya menggunakan TreeBidiMapdari perpustakaan Koleksi Apache . Saya ingin mengurutkan ini pada nilai-nilai yang ada doubles.

Metode saya adalah mengambil nilai Collectiondari menggunakan:

Collection coll = themap.values();

Yang secara alami berfungsi dengan baik.

Pertanyaan Utama: Saya sekarang ingin tahu bagaimana saya bisa mengonversi / membuang (tidak yakin mana yang benar) collke dalam Listsehingga bisa diurutkan?

Saya kemudian bermaksud untuk mengulangi Listobjek yang diurutkan , yang seharusnya dalam urutan dan mendapatkan kunci yang sesuai dari TreeBidiMap( themap) menggunakan themap.getKey(iterator.next())tempat iterator akan berada di atas daftar doubles.

Ankur
sumber
4
Anda mungkin ingin menghindari langkah ini dengan langsung menggunakan semacam SortedMap, sehingga entri berada dalam urutan alami dari kunci yang digunakan. TreeMap Java sendiri mengimplementasikan SortedMap.
Axel Knauf
TreeBidiMapadalah OrderedMap, pesanan harus ok. Penyortiran yang diperlukan dalam pertanyaan adalah pada nilai, bukan pada kunci.
Vlasec

Jawaban:

470
List list = new ArrayList(coll);
Collections.sort(list);

Seperti yang dikatakan Erel Segal Halevi di bawah ini, jika coll sudah menjadi daftar, Anda dapat melewati langkah pertama. Tapi itu akan tergantung pada internal TreeBidiMap.

List list;
if (coll instanceof List)
  list = (List)coll;
else
  list = new ArrayList(coll);
Paul Tomblin
sumber
4
Hanya untuk mencatat bahwa ada efek samping yang berbeda dari dua pendekatan: casting koleksi ke daftar dan kemudian sortir juga akan mengurutkan koleksi asli; membuat salinan tidak akan.
Barney
Pendekatan ini sangat menurunkan kinerja jika digunakan berulang kali. Lihat jawaban saya untuk solusi yang berfungsi saat itu juga, ini melibatkan koleksi khusus.
Vlasec
Ini tidak menyelesaikan kasus ketika map.values ​​() mengembalikan koleksi "kelas dalam". Kompiler melaporkan bahwa Collections.sort (Daftar <T>) tidak menerima Collections.sort (Daftar <InnerClass>). Solusinya bahkan menggunakan: Daftar <InnerClass> list = map.values ​​(). Stream (). Collect (Collectors.toList ())
Pereira
92

Sesuatu seperti ini seharusnya berfungsi, memanggil konstruktor ArrayList yang mengambil Koleksi:

List theList = new ArrayList(coll);
Jack Leow
sumber
Bagus dan sederhana.
James Gawron
33

Saya pikir jawaban Paul Tomblin mungkin sia-sia jika coll sudah menjadi daftar, karena itu akan membuat daftar baru dan menyalin semua elemen. Jika coll mengandung banyak elemen, ini mungkin membutuhkan waktu lama.

Saran saya adalah:

List list;
if (coll instanceof List)
  list = (List)coll;
else
  list = new ArrayList(coll);
Collections.sort(list);
Erel Segal-Halevi
sumber
21

Saya yakin Anda bisa menulisnya seperti ini:

coll.stream().collect(Collectors.toList())
Eyal Ofri
sumber
Cara yang lebih baik untuk berkeliling casting
Stackee007
Bagus! Ini menyelesaikan kasus saya. Map.values ​​() saya mengembalikan koleksi "kelas dalam". Kompiler melaporkan bahwa Collections.sort (Daftar <T>) tidak menerima Collections.sort (Daftar <InnerClass>).
Pereira
tidak berfungsi untuk kasus penggunaan saya di android. membutuhkan api minimum 24
ansh sachdeva
8
Collections.sort( new ArrayList( coll ) );
OscarRyz
sumber
Kehilangan referensi untuk mengakses ArrayList?
Zach Scrivena
@ Zach: mmhh poin bagus. Saya tahu ada alasan bagi saya untuk menandai ini sebagai CW. BTW ans Paul adalah satu-satunya. Saya tidak tahu mengapa dia hanya memiliki uv saya.
OscarRyz
4

@ Kunigami: Saya pikir Anda mungkin salah tentang newArrayListmetode Guava . Itu tidak memeriksa apakah Iterable adalah tipe daftar dan hanya mengembalikan daftar yang diberikan apa adanya. Itu selalu membuat daftar baru:

@GwtCompatible(serializable = true)
public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) {
  checkNotNull(elements); // for GWT
  // Let ArrayList's sizing logic work, if possible
  return (elements instanceof Collection)
      ? new ArrayList<E>(Collections2.cast(elements))
      : newArrayList(elements.iterator());
}
Nathan Perrier
sumber
Bagaimana ini tidak dipilih lebih banyak? Jawaban Kunigami salah (sejauh diasumsikan tentang implementasi yang mendasarinya).
GreenieMeanie
0

Apa yang Anda minta adalah operasi yang cukup mahal, pastikan Anda tidak perlu sering melakukannya (misalnya dalam satu siklus).

Jika tidak, Anda dapat membuat koleksi khusus. Saya datang dengan yang memiliki TreeBidiMapdan di TreeMultisetbawah tenda. Terapkan hanya apa yang Anda butuhkan dan pedulikan integritas data.

class MyCustomCollection implements Map<K, V> {
    TreeBidiMap<K, V> map;
    TreeMultiset<V> multiset;
    public V put(K key, V value) {
        removeValue(map.put(key, value));
        multiset.add(value);
    }
    public boolean remove(K key) {
        removeValue(map.remove(key));
    }
    /** removes value that was removed/replaced in map */
    private removeValue(V value) {
        if (value != null) {
            multiset.remove(value);
        }
    }
    public Set keySet() {
        return map.keySet();
    }
    public Multiset values() {
        return multiset;
    }
    // many more methods to be implemented, e.g. count, isEmpty etc.
}

Dengan cara ini, Anda telah disortir Multiset dari values(). Namun, jika Anda membutuhkannya untuk menjadi daftar (misalnya Anda memerlukan get(index)metode seperti array ), Anda harus menemukan sesuatu yang lebih kompleks.

Vlasec
sumber
keySet()dan values()Views ke aslinya Map, jadi ketika mereka diubah dukungan Mapharus dimodifikasi juga, solusi Anda tidak mendukung ini
Lino
-4

Berikut ini adalah solusi sub-optimal sebagai one-liner:

Collections.list(Collections.enumeration(coll));
Arhus
sumber