gpt4 book ai didi

Java 8 Stream 函数将变位词列表分组到列表映射中

转载 作者:搜寻专家 更新时间:2023-10-30 21:45:59 25 4
gpt4 key购买 nike

Java 8 即将发布...在学习 Streams 时,我遇到了使用其中一种新方法对字谜进行分组的场景。我面临的问题是我找不到使用 map/reduce 函数对 Strings 对象进行分组的方法。相反,我必须创建一种与 Aggregate Operations - Reduction 中记录的类似方式.

根据文档,我们可以简单地使用:

LIST<T>.stream().collect(Collectors.groupingBy(POJO::GET_METHOD))

所以Collectors.groupingBy()将根据使用的方法聚合 map 的键。然而,这种方法似乎太麻烦了,无法包装一个简单的字符串表示。

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> .基于How to convert List to 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 包装值?

最佳答案

单参数 groupingBy 收集器完全符合您的要求。它对其输入进行分类,您已经使用 sortChars(或前面示例中的 getKey)完成了该操作。分类在同一键下的每个流值都被放入一个列表中,该列表是 map 的值。因此我们有:

Map<String, List<String>> anagrams =
words2.stream().collect(Collectors.groupingBy(w -> sortChars(w)));

给出输出

{door=[odor, rood], acr=[arc, car], ghint=[night, thing], aemrst=[stream],
efirs=[fires, fries], loop=[pool, loop], aemst=[meats, mates, teams]}

您还可以使用方法引用:

Map<String, List<String>> anagrams =
words2.stream().collect(Collectors.groupingBy(GroupingAnagrams::sortChars));

如果您想对这些值做一些事情而不是建立一个列表,请使用 groupingBy 的多参数重载和“下游”收集器。例如,要计算单词数而不是构建列表,请执行以下操作:

Map<String, Long> anagrams =
words2.stream().collect(
Collectors.groupingBy(GroupingAnagrams::sortChars, Collectors.counting()));

这导致:

{door=2, acr=2, ghint=2, aemrst=1, efirs=2, loop=2, aemst=3}

编辑:

如果不清楚,sortChars 只是一个静态函数,它执行与第一个示例中的 getKey 类似的功能,但从字符串到字符串:

public static String sortChars(String input) {
char[] characters = input.toCharArray();
Arrays.sort(characters);
return new String(characters);
}

关于Java 8 Stream 函数将变位词列表分组到列表映射中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21978653/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com