Я пытаюсь решить следующие упражнения из «ядер Java для нетерпеливого» по Cay Horstmann:Streams с возвратным TreeMap некогерентных результатами
Когда кодер из
Charset
с частичным охватом Unicode не может кодировать , он заменяет его стандартным, но не всегда, кодировкой «?». Найти все замены всех доступных наборов символов, поддерживающих кодирование. Используйте методnewEncoder
, чтобы получить кодировщик, и позвоните по его методуreplacement
, чтобы получить замену . Для каждого уникального результата сообщайте канонические имена кодировок , которые его используют.
Ради образования, я решил взяться за упражнения с гигантскими однострочника использованием потокового API, несмотря на то, - на мой взгляд - это чистое решение будет разделить расчеты на ряд шагов, с промежуточные переменные между ними (конечно, это облегчило бы отладку). Без дальнейших церемоний, вот монстр кода я создал:
Charset.availableCharsets().values().stream().filter(charset -> charset.canEncode()).collect(
Collectors.groupingBy(
charset -> charset.newEncoder().replacement(),
() -> new TreeMap<>((arr1, arr2) -> Arrays.equals(arr1, arr2) == true ? 0 : Integer.compare(arr1.hashCode(), arr2.hashCode())),
Collectors.mapping(charset -> charset.name(), Collectors.toList()))).
values().stream().map(list -> list.stream().collect(Collectors.joining(", "))).forEach(System.out::println);
В основном, мы принимаем во внимание только кодировок, что canEncode
; создать Map
с replacement
как ключ и список канонических имен в качестве значений; потому что группировка не работала для массивов с реализацией по умолчанию groupingBy
, которая использует HashMap
, я решил использовать TreeMap
. Затем мы работаем с каноническими именами Lists
, присоединяем их к запятой и печати.
К сожалению, я нашел его для получения некогерентных результатов. Если я дважды запускаю функцию в той же программе, первый экземпляр возвращает результаты, состоящие из 23 Strings
, второй - только 21 Strings
. Я подозреваю, что это что-то делать с плохой реализацией Comparator
для TreeMap
, которая была определена следующим образом:
((arr1, arr2) -> Arrays.equals(arr1, arr2) == true ? 0 : Integer.compare(arr1.hashCode(), arr2.hashCode()))
Если это является причиной, что должно быть в этом случае собственно Comparator
? Кроме того, можно ли улучшить однострочный лайнер?
Мне также интересно, если такие сложные конструкции, как написанный мной код, встречаются в профессиональных программах? Может быть, только мне это кажется нечитаемым?
убедитесь, что ваш компаратор удовлетворяет следующим требованиям: * Порядок, заданный компаратором c на наборе элементов S, считается согласованным с равными тогда и только тогда, когда c.compare (e1, e2) == 0 имеет то же логическое значение как e1.equals (e2) для каждого e1 и e2 в S * – Jobin
Спасибо. Я не уверен, что в этом случае можно определить компаратор, совместимый с равными, поскольку для массивов сравниваются ссылки, и мне нужно сравнить значения, хранящиеся в этом массиве. Есть ли какая-либо другая структура данных, которую я мог бы использовать в этом случае, помимо TreeMap? – lukeg