Сортировка LongAdder в потоках

у меня есть

Map<String,LongAdder>

и я хочу сортировать по значению наилучшим образом в потоках. Это сложнее, чем с Long, потому что LongAdder не реализует Comparable, поэтому мне приходится использовать longValue (или intValue, если для создания компаратора используется вычитание).

я знаю, что могу использовать

m.entrySet().stream().sorted((a, b) -> b.getValue().intValue() - a.getValue().intValue())

но на самом деле я хочу также сортировать по ключу (String). Я также сортирую в обратном порядке.

я хочу делать

m.entrySet().stream().sorted(
Comparator.comparing((a, b) -> b.getValue().intValue() - a.getValue().intValue()))

так что я могу потом связать больше компараторов с thenComparing()

Исключением является

Lambda expression's signature does not match the signature of the functional interface method apply(T)

Но даже объявление автономного компаратора не работает:

Comparator<Map.Entry<String,LongAdder>> byCount =      Comparator.comparing((a,b) -> 
    (b.getValue().intValue() - a.getValue().intValue()));

Lambda expression's signature does not match the signature of the functional interface method apply(T)

Я не могу использовать функциональную ссылку "::", потому что это слишком много частей: Map.Entry.getValue().intValue().

Comparator.comparing не принимает Comparator — он принимает функцию, которая отображает ваш объект в сопоставимый. Кроме того, никогда не используйте вычитание для сравнения — оно может переполниться и дать вам неверный результат. Используйте Integer.compare. Кроме того, не используйте intValue, если ваши числа на самом деле длинные — опять же, вы потеряете информацию.
RealSkeptic 17.06.2019 16:19
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
111
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ваш автономный компаратор может быть исправлен для использования Function и будет выглядеть так:

Comparator<Map.Entry<String,LongAdder>> byCount = Comparator.comparingInt(e -> e.getValue().intValue());
Ответ принят как подходящий

Comparator.comparingLong - это то, что вам нужно:

Comparator<Map.Entry<String, LongAdder>> byCount =
    Comparator.comparingLong((Map.Entry<String, LongAdder> e) ->
        e.getValue().longValue()).reversed().thenComparing(...);

Важное примечание: не забудьте использовать явно типизированное лямбда-выражение, иначе цепочка методов типа comparing(...).thenComparing(...) не будет компилироваться в данном конкретном случае1.


1 - This answer explains why.

На одном уровне вы можете избежать явных типов при использовании Comparator<Map.Entry<String, LongAdder>> byCount = Map.Entry.comparingByValue(Comparator.comparingLong(LongAdde‌​r::sum).reversed( )); Но при цепочке других критериев сортировки вам в конечном итоге понадобятся явные типы, например Comparator<Map.Entry <String, LongAdder>> byCount2 = Map.Entry.<String, LongAdder>comparingByValue(Comparator. comparingLong(LongAdder::sum).reversed()).thenComparing(…);

Holger 18.06.2019 18:29

Другие вопросы по теме