Ich versuche, die folgende Übung von „Core-Java für Ungeduldige“ von Cay Horstmann zu lösen:Streams mit TreeMap Rückkehr inkohärent Ergebnisse
Wenn ein Encoder eines
Charset
mit teilweise Unicode-Abdeckung kann kein kodieren Zeichen, es ersetzt es mit einem Standard - normalerweise, aber nicht immer, die Codierung von "?". Hier finden Sie alle Ersetzungen aller verfügbaren Zeichensätze, die die Codierung unterstützen. Verwenden Sie dienewEncoder
Methode, um einen Encoder zu erhalten, und rufen Sie diereplacement
Methode auf, um den Ersatz zu erhalten. Geben Sie für jedes eindeutige Ergebnis die kanonischen Namen der Zeichensätze an, die es verwenden.
Aus Gründen der Ausbildung hat ich beschlossen, die Übung mit gargantuan Einzeiler mit dem Streaming-API, obwohl in Angriff zu nehmen - meiner Meinung nach - eine saubere Lösung, die Berechnungen in mehreren Schritten unterteilen würde, mit Zwischenvariablen dazwischen (sicherlich würde es das Debuggen erleichtern). Ohne weitere Umschweife, hier ein Monster von Code, die ich erstellt haben:
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);
Grundsätzlich berücksichtigen wir nur die charsets dass canEncode
; Erstellen Sie eine Map
mit replacement
als Schlüssel und eine Liste der kanonischen Namen als Werte; Da die Gruppierung für Arrays mit der Standardimplementierung groupingBy
, die HashMap
verwendet, nicht funktioniert, habe ich mich entschieden, zu verwenden. Wir arbeiten dann mit den Lists
kanonischen Namen, verbinden sie mit Komma und drucken.
Leider habe ich gefunden, dass es zu inkohärenten Ergebnissen führt. Wenn ich die Funktion zweimal im selben Programm ausführe, gibt die erste Instanz Ergebnisse zurück, die aus 23 Strings
bestehen, der zweite - nur 21 Strings
. Ich vermute, es hat etwas mit einer schlechten Umsetzung Comparator
für TreeMap
zu tun, das wurde wie folgt definiert:
((arr1, arr2) -> Arrays.equals(arr1, arr2) == true ? 0 : Integer.compare(arr1.hashCode(), arr2.hashCode()))
Wenn das die Ursache ist, was eine richtiges Comparator
in diesem Fall sein sollte? Abgesehen davon, kann der One-Liner in irgendeiner Weise verbessert werden?
Ich bin auch neugierig, wenn solche verworrenen Konstrukte wie der Code, den ich geschrieben habe, in professionellen Programmen angetroffen werden? Vielleicht finde ich es nur für mich unleserlich?
stellen Sie sicher, dass Ihr Vergleicher die folgenden erfüllen * Die Reihenfolge, die von einem Komparator c auf einer Menge von Elementen S auferlegt wird gesagt, mit genau gleich zu sein, wenn c.compare (e1, e2) == 0 hat Derselbe boolesche Wert wie e1.equals (e2) für jedes e1 und e2 in S * – Jobin
Vielen Dank. Ich bin nicht sicher, ob ein Komparator, der mit equals konsistent ist, in diesem Fall definiert werden kann, da equars für Arrays Referenzen vergleicht und ich die in diesem Array gespeicherten Werte vergleichen muss. Gibt es eine andere Datenstruktur, die ich in diesem Fall verwenden könnte, abgesehen von TreeMap? – lukeg