Как отсортировать набор в список в Java?


169

В Java у меня есть Set, и я хочу превратить его в отсортированный List. Есть ли в java.util.Collectionsпакете метод , который сделает это для меня?

Ответы:


214

Ответ, предоставленный ФП , не самый лучший. Это неэффективно, так как создает новые List и ненужный новый массив. Кроме того, он вызывает «непроверенные» предупреждения из-за проблем безопасности типов вокруг универсальных массивов.

Вместо этого используйте что-то вроде этого:

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

Вот пример использования:

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

3
Спасибо! Это SuppressWarnings всегда беспокоило меня.
Джереми Стейн

4
@sunleo Этот Utilкласс содержит asSortedList()метод, который я написал. Другими словами, вы Utilсами пишете класс и помещаете в него этот код.
Эриксон

1
ха-ха, я думал, что из пакета по умолчанию, как java.util хорошо, спасибо.
Sunleo

3
Это может быть хорошей универсальной функцией Utility, но на самом деле она неэффективна. Рассмотрите возможность сортировки на месте, убедившись, что у вас есть набор в правильном контейнере для начала. Также рассмотрите возможность использования TreeSet в качестве прямого контейнера ваших данных. Если ваши данные так или иначе должны быть уникальными, и вам нужен набор, то используйте TreeSet, чтобы поймать двух мух в одном ряду.
YoYo

1
Как примечание для людей, которые только читают верхний ответ: посмотрите ответ nschum ниже, который использует потоки Java 8. Если вы можете использовать Java 8, пойти на это. они более гибкие и эффективные.
Felk

74

Сортированный набор:

return new TreeSet(setIWantSorted);

или:

return new ArrayList(new TreeSet(setIWantSorted));

Это была моя первая мысль, но спрашивающий хотел получить список
Alex B

@ Алекс: Этот подход все еще можно использовать; вернуть новый ArrayList (новый TreeSet (setIWantSorted))
Jonik

1
Я на самом деле использовал это решение, но я бы не советовал. Как говорится в документации по TreeSet (см. Download.oracle.com/javase/1.4.2/docs/api/java/util/… ), он эффективно использует метод compareTo () вместо метода equals () - так что если вы иметь два объекта в наборе, которые имеют одинаковый результат equals (), они будут рассматриваться как дубликаты и, как таковые, не будут добавлены в TreeSet. Осторожно.
fwielstra

24
@fwielstra: Как вы можете иметь объекты, которые равны на входе, так как вход также является Set?
ryanprayogo

2
@ryanprayogo Стоит отметить, что new TreeSetпринимает Collections, а не только Sets. Не каждый, кто читает этот ответ, будет использовать Set, хотя это то, что задает оригинальный вопрос.
Крис

44
List myList = new ArrayList(collection);
Collections.sort(myList);

... должен сделать свое дело однако. Добавьте аромат с Generics, где это применимо.


У меня был полезный фрагмент, который я хотел пожертвовать сообществу. Когда я искал информацию, я не мог ее найти. Я пытался облегчить работу следующего человека. stackoverflow.com/questions/18557/…
Джереми Стейн

1
Да, конечно, но та ссылка, которую вы предоставили, на самом деле говорит о реальных вопросах (то есть тех, на которые нет ответа, затем найдите его). Ваш вопрос здесь был только для того, чтобы дать ответ ... Я мог бы на самом деле ввести сотни вопросов и ответить сам; не в этом дело!
Себ

5
@Seb: я не согласен. Я не вижу ничего плохого в этом вопросе. Очевидно, это был не очень простой вопрос, и теперь он знает лучший способ, чем раньше!
Майкл Майерс

3
Это был настоящий вопрос, но я сам нашел ответ после того, как Google вышел из строя. Stackoverflow не существовало в то время. Я разместил его на своем сайте, и это помогло кому-то еще, поэтому я подумал, что это может быть полезно здесь.
Джереми Стейн

Бонус: и если вам случается сортировать свой собственный тип объекта, то вы всегда можете реализовать Comparableи переопределить compareToметод.
nabster

42

Вот как вы можете сделать это с помощью потоков Java 8:

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

или с пользовательским компаратором:

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

9

Всегда безопасно использовать интерфейс Comparator или Comparable для обеспечения реализации сортировки (если объект не является классами String или Wrapper для примитивных типов данных). В качестве примера реализации компаратора для сортировки сотрудников по имени

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

Компаратор полезен, когда вам нужно иметь другой алгоритм сортировки для одного и того же объекта (например, имя emp, имя зарплаты и т. Д.). Однорежимная сортировка может быть реализована с помощью сопоставимого интерфейса с требуемым объектом.


5

Там нет единого способа сделать это. Использовать это:

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

Существует также функция Collections.sort, но я думаю, что она делает то же самое. +1 в любом случае.
CookieOfFortune

1
Collections.sort принимает список в качестве параметра.
Джереми Стейн

3

Вы можете преобразовать набор в ArrayList, где вы можете отсортировать, ArrayListиспользуяCollections.sort(List) .

Вот код:

keySet = (Set) map.keySet();
ArrayList list = new ArrayList(keySet);     
Collections.sort(list);

3
TreeSet sortedset = new TreeSet();
sortedset.addAll(originalset);

list.addAll(sortedset);

где originalset = несортированный набор и list = список, который нужно вернуть


TreeSet также удаляет дубликаты списка, что может привести к неверному результату, если вы этого не предполагаете.
Антонимонори

2

@ Джереми Стейн Я хотел реализовать тот же код. Также я хотел отсортировать набор в список, поэтому вместо использования Set я конвертировал набор значений в список и сортировал этот список по одной переменной. Этот код помог мне,

set.stream().sorted(Comparator.comparing(ModelClassName::sortingVariableName)).collect(Collectors.toList());

0

Я использую этот код, который я считаю более практичным, чем принятый ответ выше:

List<Thing> thingList = new ArrayList<>(thingSet);
thingList.sort((thing1, thing2) -> thing1.getName().compareToIgnoreCase(thing2.getName()));
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.