Java 8 即将发布...在学习 Streams 时,我遇到了一个关于使用一种新方法对字谜进行分组的场景.我面临的问题是我找不到使用 map/reduce 函数对字符串对象进行分组的方法.相反,我必须创建与 Aggregate Operations - Reduction 中记录的类似方式.
Java 8 is about to be released... While learning about Streams, I got into a scenario about grouping anagrams using one of the new ways. The problem I'm facing is that I can't find a way to group Strings objects using the map/reduce functions. Instead, I had to create a similar way as documented at Aggregate Operations - Reduction.
根据文档,我们可以简单地使用:
Based on the documentation, we can simply use:
LIST<T>.stream().collect(Collectors.groupingBy(POJO::GET_METHOD))
这样 Collectors.groupingBy() 将根据使用的方法聚合地图的键.但是,这种方法对于包装简单的 String 表示似乎太麻烦了.
So that Collectors.groupingBy() will aggregate the keys of the map based on the method used. However, this approach is too seems to be cumbersome to wrap a simple String presentation.
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>.基于如何将列表转换为地图,我有以下内容:
Instead, I'm looking for a simpler and more direct solution that uses the new map/reduce functions to accumulate the results into the similar interface Map<String, List<String>. Based on How to convert List to Map, I have the following:
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.
But this code generates a key collision as it is a Map of 1-1.
Exception in thread "main" java.lang.IllegalStateException: Duplicate key pool
这是有道理的...有没有办法将它们分组到与 groupingBy 的第一个解决方案类似的输出中,但不使用包装值的 POJO?
which makes sense... Is there a way to group them into the similar output as the first solution with groupingBy, but without using a POJO wrapping the values?
单参数 groupingBy 收集器完全符合您的要求.它对其输入进行分类,您已经使用 sortChars(或前面示例中的 getKey)完成了这些工作.归类在同一键下的每个流值都被放入一个列表中,该列表是映射的值.因此我们有:
The single-argument groupingBy collector does exactly what you want to do. It classifies its input, which you've already done using sortChars (or getKey in the earlier example). Each stream value that's classified under the same key gets put into a list which is the map's value. Thus we have:
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]}
您也可以使用方法参考:
You could also use a method reference:
Map<String, List<String>> anagrams =
words2.stream().collect(Collectors.groupingBy(GroupingAnagrams::sortChars));
如果您想对这些值做一些事情而不是建立一个列表,请使用 groupingBy 的多参数重载和下游"收集器.例如,要计算单词而不是建立一个列表,请执行以下操作:
If you want to do something with the values other than building up a list, use a multi-arg overload of groupingBy and a "downstream" collector. For example, to count the words instead of building up a list, do this:
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 类似的功能,但从字符串到字符串:
In case it wasn't clear, sortChars is simply a static function that performs a similar function to what getKey did in the first example, but from string to string:
public static String sortChars(String input) {
char[] characters = input.toCharArray();
Arrays.sort(characters);
return new String(characters);
}
这篇关于Java 8 Stream 函数将字谜列表分组为列表映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!
如何检测 32 位 int 上的整数溢出?How can I detect integer overflow on 32 bits int?(如何检测 32 位 int 上的整数溢出?)
return 语句之前的局部变量,这有关系吗?Local variables before return statements, does it matter?(return 语句之前的局部变量,这有关系吗?)
如何将整数转换为整数?How to convert Integer to int?(如何将整数转换为整数?)
如何在给定范围内创建一个随机打乱数字的 intHow do I create an int array with randomly shuffled numbers in a given range(如何在给定范围内创建一个随机打乱数字的 int 数组)
java的行为不一致==Inconsistent behavior on java#39;s ==(java的行为不一致==)
为什么 Java 能够将 0xff000000 存储为 int?Why is Java able to store 0xff000000 as an int?(为什么 Java 能够将 0xff000000 存储为 int?)