Bir Koleksiyon Listeye nasıl dönüştürülür?


295

Ben kullanıyorum TreeBidiMapgelen Apaçi Koleksiyonları kütüphanede. Bunu olan değerlere göre sıralamak istiyorum doubles.

Benim yöntemim Collectionkullanarak değerleri bir almaktır:

Collection coll = themap.values();

Hangi doğal olarak iyi çalışıyor.

Ana Soru: Şimdi nasıl sıralanabilir böylece collbir dönüştürmek / (hangisinin doğru olduğundan emin değilim) bilmek istiyorum List?

Daha sonra Listsırayla olması gereken yinelenen nesne üzerinde yineleme ve yineleyici listesinin üzerinde nerede olacak kullanarak TreeBidiMap( themap) gelen uygun anahtarları almak niyetinde .themap.getKey(iterator.next())doubles


4
Doğrudan bir çeşit SortedMap kullanarak bu adımdan kaçınmak isteyebilirsiniz, böylece girişler kullanılan anahtarların doğal düzenindedir. Java'nın kendi TreeMap'i SortedMap'i uygular.
Axel Knauf

TreeBidiMapbir OrderedMap, sipariş tamam olmalıdır. Soruda istenen sıralama, anahtarlarda değil, değerler üzerindedir.
Vlasec

Yanıtlar:


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

Erel Segal Halevi'nin dediği gibi, coll zaten bir listeyse, birinci adımı atlayabilirsiniz. Ancak bu TreeBidiMap'in iç kısmına bağlıdır.

List list;
if (coll instanceof List)
  list = (List)coll;
else
  list = new ArrayList(coll);

4
İki yaklaşımın farklı yan etkileri olduğunu unutmayın: koleksiyonun bir listeye dökülmesi ve ardından sıralama, orijinal koleksiyonu da sıralar; bir kopya oluşturmak olmaz.
Barney

Bu yaklaşım, tekrar tekrar kullanılması durumunda performansı büyük ölçüde düşürür. Anında çalışan bir çözüm için cevabımı görün, özel bir koleksiyon içerir.
Vlasec

Map.values ​​() bir "iç sınıf" koleksiyonu döndürdüğünde bu durum çözümlenmez. Derleyici Collections.sort (Liste <T>) 'nin Collections.sort (Liste <InnerClass>) kabul etmediğini bildirir. Çözüm bile kullanıldı: Liste <InnerClass> list = map.values ​​(). Stream (). Collect (Collectors.toList ())
Pereira


33

Sanırım Paul Tomblin, coll'ın zaten bir liste olması durumunda cevabını boşa harcayabilir, çünkü yeni bir liste oluşturacak ve tüm öğeleri kopyalayacaktır. Coll çok sayıda elemeent içeriyorsa, bu uzun zaman alabilir.

Benim önerim:

List list;
if (coll instanceof List)
  list = (List)coll;
else
  list = new ArrayList(coll);
Collections.sort(list);

21

Ben böyle yazabilirsiniz inanıyorum:

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

Döküm almak için daha iyi bir yol
Stackee007

Harika! Bu davamı çözdü. Map.values ​​() yöntemim bir "iç sınıf" koleksiyonu döndürür. Derleyici Collections.sort (Liste <T>) 'nin Collections.sort (Liste <InnerClass>) kabul etmediğini bildirdi.
Pereira

android benim kullanım dava için işe yaramadı. minimum api 24 gerektirir
ansh sachdeva

8
Collections.sort( new ArrayList( coll ) );

ArrayList'e erişmek için başvuru eksik mi?
Zach Scrivena

@Zach: mmhh iyi bir nokta. Bunu CW olarak işaretlemem için bir neden olduğunu biliyordum. BTW Paul'un ans'ı. Neden sadece benim uv'm olduğunu bilmiyorum.
OscarRyz

4

@Kunigami: Sanırım Guava'nın newArrayListyöntemi hakkında yanılmış olabilirsin . Yinelenebilir bir Liste türü olup olmadığını kontrol etmez ve verilen Listeyi olduğu gibi döndürür. Her zaman yeni bir liste oluşturur:

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

Nasıl daha fazla oy kullanılmıyor? Kunigami'nin cevabı yanlıştır (temel uygulama hakkında varsayıldığı sürece).
GreenieMeanie

1

Siparişi korurken değiştirilemez ListeList#copyOf döndüren Java 14 tanıtıldı :

List<Integer> list = List.copyOf(coll);

0

İstediğiniz şey oldukça pahalı bir işlemdir, sık sık (örneğin bir döngüde) yapmanız gerekmediğinden emin olun.

Aksi takdirde, özel bir koleksiyon oluşturabilirsiniz. Senin TreeBidiMapve TreeMultisetkaputun altında bir tane buldum . Yalnızca ihtiyacınız olanı uygulayın ve veri bütünlüğüne önem verin.

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.
}

Bu şekilde, tarafından döndürülen bir sıralamanız var . Ancak, bir liste olması gerekiyorsa (örneğin, dizi benzeri bir yönteme ihtiyacınız varsa ), daha karmaşık bir şey icat etmeniz gerekir.Multisetvalues()get(index)


keySet()ve values()orijinalin Görünümleridir Map, bu nedenle değiştirildiklerinde desteğin Mapde değiştirilmesi gerekir, çözümünüz bunu desteklemez
Lino

-4

İşte tek astar olarak alt optimal bir çözüm:

Collections.list(Collections.enumeration(coll));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.