Java 8 がリリースされようとしています... Streams について学習しているときに、新しい方法の 1 つを使用してアナグラムをグループ化するというシナリオに入りました。私が直面している問題は、map/reduce 関数を使用して Strings オブジェクトをグループ化する方法が見つからないことです。代わりに、 Aggregate Operations - Reductionに記載されているのと同様の方法を作成する必要がありました。
ドキュメントに基づいて、次を簡単に使用できます。
LIST<T>.stream().collect(Collectors.groupingBy(POJO::GET_METHOD))
したがって、Collectors.groupingBy()
使用される方法に基づいてマップのキーが集約されます。ただし、このアプローチは、単純な String プレゼンテーションをラップするにはあまりにも面倒です。
public class AnagramsGrouping {
static class Word {
public String original;
public Word(String word) {
original = word;
}
public String getKey() {
char[] characters = input.toCharArray();
Arrays.sort(characters);
return new String(characters);
}
public String toString() {
return original;
}
}
public static void main(String[] args) {
List<Word> words = Arrays.asList(new Word("pool"), new Word("loop"),
new Word("stream"), new Word("arc"), new Word("odor"),
new Word("car"), new Word("rood"), new Word("meats"),
new Word("fires"), new Word("fries"), new Word("night"),
new Word("thing"), new Word("mates"), new Word("teams"));
Map<String, List<Word>> anagrams = words.stream().collect(
Collectors.groupingBy(Word::getKey));
System.out.println(anagrams);
}
}
これにより、次のように出力されます。
{door=[odor, rood], acr=[arc, car], ghint=[night, thing],
aemrst=[stream], efirs=[fires, fries], loop=[pool, loop],
aemst=[meats, mates, teams]}
代わりに、新しい map/reduce 関数を使用して結果を同様のインターフェースに蓄積する、よりシンプルで直接的なソリューションを探していますMap<String, List<String>
。List を Map に変換する方法に基づいて、次のものがあります。
List<String> words2 = Arrays.asList("pool", "loop", "stream", "arc",
"odor", "car", "rood", "meats", "fires", "fries",
"night", "thing", "mates", "teams");
words2.stream().collect(Collectors.toMap(w -> sortChars(w), w -> w));
しかし、このコードは 1-1 の Map であるため、キーの衝突が発生します。
Exception in thread "main" java.lang.IllegalStateException: Duplicate key pool
これは理にかなっています...groupingBy
値をラップするPOJOを使用せずに、最初のソリューションと同様の出力にそれらをグループ化する方法はありますか?