Jak przekonwertować kolekcję na listę?


294

Korzystam TreeBidiMapz biblioteki kolekcji Apache . Chcę posortować to według wartości, które są doubles.

Moja metoda polega na pobraniu jednej Collectionz wartości za pomocą:

Collection coll = themap.values();

Co oczywiście działa dobrze.

Główne pytanie: Chcę teraz wiedzieć, jak mogę przekonwertować / rzutować (nie jestem pewien, co jest poprawne) collna plik, Listaby można go było posortować?

Zamierzam następnie iterować posortowany Listobiekt, który powinien być w porządku, i uzyskać odpowiednie klucze z TreeBidiMap( themap), używając themap.getKey(iterator.next())miejsca, w którym iterator będzie nad listą doubles.


4
Możesz uniknąć tego kroku, bezpośrednio używając jakiegoś SortedMap, więc wpisy są w naturalnej kolejności używanych kluczy. Własna TreeMap w Javie implementuje SortedMap.
Axel Knauf

TreeBidiMapjest OrderedMap, zamówienie powinno być w porządku. Sortowanie wymagane w pytaniu dotyczy wartości, a nie kluczy.
Vlasec

Odpowiedzi:


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

Jak mówi poniżej Erel Segal Halevi, jeśli coll jest już listą, możesz pominąć krok pierwszy. Ale to zależy od wewnętrznych elementów TreeBidiMap.

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

4
Należy zauważyć, że oba podejścia mają różne skutki uboczne: rzutowanie kolekcji na listę, a następnie sortowanie posortuje również oryginalną kolekcję; tworzenie kopii nie będzie.
Barney

Takie podejście znacznie obniża wydajność, jeśli jest używane wielokrotnie. Zobacz moją odpowiedź na rozwiązanie, które działa w locie i obejmuje kolekcję niestandardową.
Vlasec,

Nie rozwiązuje to przypadku, gdy map.values ​​() zwraca kolekcję „klasy wewnętrznej”. Kompilator zgłasza, że ​​Kolekcje.sort (Lista <T>) nie akceptuje Kolekcje.sort (Lista <Klasa wewnętrzna>). Rozwiązaniem było nawet użycie: List <InnerClass> list = map.values ​​(). Stream (). Collect (Collectors.toList ())
Pereira


33

Myślę, że odpowiedź Paula Tomblina może być marnotrawstwem, jeśli coll jest już listą, ponieważ utworzy nową listę i skopiuje wszystkie elementy. Jeśli coll zawiera wiele elementów, może to zająć dużo czasu.

Moja sugestia to:

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

21

Wierzę, że możesz to tak napisać:

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

Lepszy sposób na obejście castingu
Stackee007

Świetny! To rozwiązało moją sprawę. Moja map.values ​​() zwraca kolekcję „klasy wewnętrznej”. Kompilator zgłosił, że Kolekcje.sort (Lista <T>) nie akceptuje Kolekcje.sort (Lista <Klasa wewnętrzna>).
Pereira

nie działało w moim przypadku użycia w Androidzie. wymaga minimalnego api 24
ansh sachdeva

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

Brakuje odniesienia do dostępu do ArrayList?
Zach Scrivena

@Zach: mmhh good point. Wiedziałem, że mam powód, aby oznaczyć to jako CW. BTW, ans Paul jest tym jedynym. Nie wiem, dlaczego ma tylko moją ultrafiolet.
OscarRyz

4

@Kunigami: Myślę, że możesz się mylić co do newArrayListmetody Guavy . Nie sprawdza, czy Iterable jest typem List, i po prostu zwraca daną Listę taką, jaka jest. To zawsze tworzy nową listę:

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

Jak to nie jest więcej głosowane? Odpowiedź Kunigami jest niepoprawna (o ile zakłada o podstawowej implementacji).
GreenieMeanie

0

To, czego żądasz, jest dość kosztowną operacją, upewnij się, że nie musisz tego robić często (np. W cyklu).

W przeciwnym razie możesz utworzyć własną kolekcję. Wymyśliłem taki, który ma twoje TreeBidiMapi TreeMultisetpod maską. Wdrażaj tylko to, czego potrzebujesz i dbaj o integralność danych.

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

W ten sposób masz posortowane Multiset wrócił z values(). Jednak jeśli potrzebujesz, aby była to lista (np. Potrzebujesz tablicy podobnej do tablicyget(index) ), musisz wymyślić coś bardziej złożonego.


keySet()i values()są widokami oryginału Map, więc kiedy zostaną zmodyfikowane, należy również zmodyfikować podkład Map, twoje rozwiązanie tego nie obsługuje
Lino

-4

Oto nieoptymalne rozwiązanie jako jedna linijka:

Collections.list(Collections.enumeration(coll));
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.