Jak posortować zestaw do listy w Javie?

169

W Javie mam Seti chcę przekształcić go w posortowany List. Czy w java.util.Collectionspakiecie jest metoda , która zrobi to za mnie?

Jeremy Stein
źródło

Odpowiedzi:

214

Odpowiedź udzielona przez PO nie jest najlepsza. Jest nieefektywny, ponieważ tworzy nową List i niepotrzebną nową tablicę. Ponadto generuje „niesprawdzone” ostrzeżenia z powodu problemów z bezpieczeństwem typów związanych z tablicami generycznymi.

Zamiast tego użyj czegoś takiego:

public static
<T extends Comparable<? super T>> List<T> asSortedList(Collection<T> c) {
  List<T> list = new ArrayList<T>(c);
  java.util.Collections.sort(list);
  return list;
}

Oto przykład użycia:

Map<Integer, String> map = new HashMap<Integer, String>();
/* Add entries to the map. */
...
/* Now get a sorted list of the *values* in the map. */
Collection<String> unsorted = map.values();
List<String> sorted = Util.asSortedList(unsorted);
erickson
źródło
3
Dzięki! To SuppressWarnings zawsze mi przeszkadzało.
Jeremy Stein
4
@sunleo UtilKlasa to ta, która zawiera asSortedList()metodę, którą napisałem. Innymi słowy, sam piszesz Utilklasę i umieszczasz w niej kod.
erickson
1
ha ha Myślałem, że pochodzi z domyślnego pakietu java.util ok, dziękuję.
sunleo
3
Może to być fajna ogólna funkcja Utility, ale faktem jest, że nadal nie jest wydajna. Rozważ sortowanie na miejscu, upewniając się, że masz zestaw w odpowiednim pojemniku na początek. Rozważ także użycie TreeSet jako bezpośredniego kontenera danych. Jeśli twoje dane i tak muszą być unikalne i potrzebujesz zestawu, użyj TreeSet, aby złapać dwie muchy w jednym uderzeniu.
YoYo,
1
Uwaga dla ludzi, którzy czytają tylko pierwszą odpowiedź: spójrz na odpowiedź nschum poniżej, która wykorzystuje strumienie Java 8. Jeśli możesz używać Java 8, zrób to. są bardziej elastyczne i wydajne.
Felk
74

Posortowany zestaw:

return new TreeSet(setIWantSorted);

lub:

return new ArrayList(new TreeSet(setIWantSorted));
Steve B.
źródło
To była moja pierwsza myśl, ale pytający chciał mieć Listę
Alex B
@Alex: Nadal można zastosować to podejście; return new ArrayList (new TreeSet (setIWantSorted))
Jonik
1
Właściwie korzystałem z tego rozwiązania, ale nie radziłbym tego. Zgodnie z dokumentacją TreeSet (patrz download.oracle.com/javase/1.4.2/docs/api/java/util/… ), efektywnie używa ona metody compareTo () zamiast metody equals () - więc jeśli mają w zestawie dwa obiekty, które mają ten sam wynik equals (), będą one postrzegane jako duplikaty i jako takie nie zostaną dodane do TreeSet. Strzec się.
fwielstra
24
@fwielstra: Jak możesz mieć obiekty, które są równe na wejściu, skoro dane wejściowe również są Set?
ryanprayogo
2
@ryanprayogo Warto wspomnieć, ponieważ new TreeSetakceptuje Collections, a nie tylko Sets. Nie każdy, kto czyta tę odpowiedź, będzie używał znaku Set, mimo że to właśnie dotyczy pierwotnego pytania.
Chris
44
List myList = new ArrayList(collection);
Collections.sort(myList);

… Powinien jednak załatwić sprawę. W razie potrzeby dodaj do smaku leki generyczne.

Esko
źródło
Miałem przydatny fragment, który chciałem przekazać społeczności. Kiedy szukałem informacji, nie mogłem ich znaleźć. Starałem się ułatwić pracę następnej osobie. stackoverflow.com/questions/18557/…
Jeremy Stein
1
Tak, jasne, ale ten link, który podałeś, w rzeczywistości dotyczy prawdziwych pytań (tj. Tych, na które nie ma odpowiedzi, a następnie je znajdź). Twoje pytanie było tutaj tylko po to, aby udzielić odpowiedzi ... Właściwie mogłem wprowadzić setki pytań i samemu odpowiedzieć; nie o to chodzi!
Seb
5
@Seb: Nie zgadzam się. Nie widzę nic złego w tym pytaniu. To oczywiście nie było niezwykle proste pytanie, a teraz zna lepszy sposób niż wcześniej!
Michael Myers
3
To było prawdziwe pytanie, ale sam znalazłem odpowiedź po tym, jak Google wyszło krótko. Stackoverflow wtedy nie istniał. Umieściłem to na mojej stronie internetowej i pomogło to komuś innemu, więc pomyślałem, że może się tu przydać.
Jeremy Stein
Bonus: A jeśli sortujesz własny typ obiektu, zawsze możesz zaimplementować Comparablei przesłonić compareTometodę.
nabster
42

Oto, jak możesz to zrobić ze strumieniami Java 8:

mySet.stream().sorted().collect(Collectors.toList());

lub z niestandardowym komparatorem:

mySet.stream().sorted(myComparator).collect(Collectors.toList());
nschum
źródło
9

Zawsze można bezpiecznie używać interfejsu Comparator lub Comparable do zapewnienia implementacji sortowania (jeśli obiekt nie jest klasą String lub Wrapper dla pierwotnych typów danych). Jako przykład implementacji komparatora do sortowania pracowników na podstawie nazwiska

    List<Employees> empList = new LinkedList<Employees>(EmpSet);

    class EmployeeComparator implements Comparator<Employee> {

            public int compare(Employee e1, Employee e2) {
                return e1.getName().compareTo(e2.getName());
            }

        }

   Collections.sort(empList , new EmployeeComparator ());

Komparator jest przydatny, gdy musisz mieć inny algorytm sortowania dla tego samego obiektu (powiedz nazwę emp., Wynagrodzenie emp. Itp.). Sortowanie w trybie pojedynczym można zaimplementować za pomocą interfejsu Comparable w wymaganym obiekcie.

Satheesh Cheveri
źródło
5

Nie ma jednej metody, aby to zrobić. Użyj tego:

@SuppressWarnings("unchecked")
public static <T extends Comparable> List<T> asSortedList(Collection<T> collection) {
  T[] array = collection.toArray(
    (T[])new Comparable[collection.size()]);
  Arrays.sort(array);
  return Arrays.asList(array);
}
Jeremy Stein
źródło
Istnieje również funkcja Collections.sort, ale myślę, że robi to samo. W każdym razie +1.
CookieOfFortune
1
Kolekcje.sort przyjmuje listę jako parametr.
Jeremy Stein
3

Możesz przekonwertować zestaw na plik ArrayList, w którym możesz sortować ArrayListusing Collections.sort(List).

Oto kod:

keySet = (Set) map.keySet();
ArrayList list = new ArrayList(keySet);     
Collections.sort(list);
Amit
źródło
3
TreeSet sortedset = new TreeSet();
sortedset.addAll(originalset);

list.addAll(sortedset);

gdzie zestaw oryginałów = zestaw nieposortowany i lista = lista do zwrócenia

Sujith Mohan
źródło
TreeSet usuwa również duplikaty z listy, co może skutkować nieprawidłowym wynikiem, jeśli tego nie założysz.
anthonymonori
2

@Jeremy Stein Chciałem zaimplementować ten sam kod. Chciałem również posortować zestaw do listy, więc zamiast używać Set, przekonwertowałem ustawione wartości na List i posortowałem tę listę według jednej ze zmiennych. Ten kod mi pomógł,

set.stream().sorted(Comparator.comparing(ModelClassName::sortingVariableName)).collect(Collectors.toList());
Deepak Kumbhar
źródło
0

Używam tego kodu, który wydaje mi się bardziej praktyczny niż zaakceptowana odpowiedź powyżej:

List<Thing> thingList = new ArrayList<>(thingSet);
thingList.sort((thing1, thing2) -> thing1.getName().compareToIgnoreCase(thing2.getName()));
nn4l
źródło