Зачем нам нужна сортировка List с помощью метода Collection.sort ()? - PullRequest
1 голос
/ 24 января 2020

Я планирую сортировать ключи из хэш-карты. Я использую индивидуальный метод сортировки.

Следующий код дает мне ошибка времени компиляции при compareTo () метод, в котором я использую Установить как коллекцию

Set<String> set = map.keySet();
Collections.sort(set, (a, b) -> map.get(a) == map.get(b) ?  a.compareTo(b) : map.get(b) - map.get(a));

Если я преобразую Установить в Список , а затем отсортировать, то все работает нормально .

List<String> words = new ArrayList<>(map.keySet());
Collections.sort(words, (a, b) -> map.get(a) == map.get(b) ?  a.compareTo(b) : map.get(b) - map.get(a));

По какой причине мне нужно преобразовать в список для сортировки коллекции? Почему я не могу отсортировать, используя Set?

Ответы [ 2 ]

2 голосов
/ 27 января 2020

A Set не имеет API для изменения порядка. Вы заметите себя, если попытаетесь, например, поменять местами первый и второй элементы Set.

. Кроме того, у наборов есть свои контракты, касающиеся порядка, который будет нарушен, если вы сможете изменить его извне

  • HashSet и набор ключей HashMap не поддерживают порядок вообще. Это общее предположение для наборов, если не указан другой контракт
  • LinkedHashSet, а набор ключей LinkedHashMap будет отражать порядок вставки
  • TreeSet и набор ключей TreeMap используйте естественный порядок ключей или порядок явно определенного компаратора. Все реализации SortedSet связаны с Comparator или естественным порядком ключей.

Для сортировки чего-либо вам нужна коллекция, которая поддерживает порядок и имеет API, поддерживающий изменение заказ.

A List является естественным кандидатом. Вы также можете сортировать массивы. Поскольку LinkedHashMap отражает порядок вставки, вы можете создать LinkedHashMap с указанным c порядком, добавив элементы в нужном порядке:

map = map.entrySet().stream()
    .sorted(Map.Entry.<String,Integer>comparingByValue().reversed()
                     .thenComparing(Map.Entry::getKey))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                              (a,b)->b, LinkedHashMap::new));

Кроме того, ваш компаратор выглядит испорченным. Термин map.get(b) - map.get(a) указывает, что значения являются числовыми, в приведенных выше примерах я предположил Integer, но map.get(a) == map.get(b) сравнивает ссылки объектов в штучной упаковке.

И в случае Integer, разница map.get(b) - map.get(a) может переполниться. Вместо этого следует использовать Integer.compare(map.get(b), map.get(a).

Или использовать фабричные методы для компараторов, когда это применимо

List<String> words = new ArrayList<>(map.keySet());
words.sort(Comparator.<String>comparingInt(map::get).reversed()
                     .thenComparing(Comparator.naturalOrder()));
1 голос
/ 29 января 2020

По определению в Java, Set НЕ является упорядоченной коллекцией.

Мы не можем отсортировать коллекцию Java Set, вызвав метод Collections.sort() на наборе.

Нет прямой поддержки сортировки наборов в Java. Чтобы отсортировать набор, выполните следующие действия:

  • Преобразование набора в список.
  • Сортировка списка с использованием Collections.sort() API.
  • Преобразование списка обратно в набор.

ИЛИ

Мы можем использовать отсортированную реализацию набора.

Согласно следующей диаграмме HashSet , LinkedHashSet и TreeSet являются реализациями Set.

  • HashSet: неупорядочено
  • LinkedHashSet: Порядок вставки
  • TreeSet: Упорядоченный (естественный порядок, то есть алфавит c, alphanumeri c или хронологический)

Примечание: HashSet является реализацией по умолчанию используется в большинстве случаев.

enter image description here

Ссылка на схему: https://dzone.com/articles/an-introduction-to-the-java-collections-framework

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...