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.


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);

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


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);

21

Saya yakin Anda bisa menulisnya seperti ini:

coll.stream().collect(Collectors.toList())

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 ) );

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());
}

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.


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));
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.