Java 使用流计算句子中每个字母的出现次数

Java 使用流计算句子中每个字母的出现次数,java,java-stream,Java,Java Stream,我想计算句子中每个字母的出现次数,并将结果存储在Map中。这可以很容易地用一个简单的循环来完成,但作为练习,我想用流来编写它。我想使用collect(toMap())生成一个映射,其值是字符本身(因此我使用Function.identity())和出现次数。我提出了以下(非编译)代码: 请尝试以下操作: String string ="a simple sentence"; Map<String, Long> map = Arrays.stream(string.split(""

我想计算句子中每个字母的出现次数,并将结果存储在
Map
中。这可以很容易地用一个简单的循环来完成,但作为练习,我想用流来编写它。我想使用
collect(toMap())
生成一个映射,其值是字符本身(因此我使用
Function.identity()
)和出现次数。我提出了以下(非编译)代码:

请尝试以下操作:

String string ="a simple sentence";
Map<String, Long> map = 
 Arrays.stream(string.split("")).
 collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
String String=“一个简单的句子”;
地图=
Arrays.stream(string.split(“”)。
collect(Collectors.groupingBy(Function.identity(),Collectors.counting());

您实际上已经接近,要完成您已经开始的操作,您需要使用
mapToObj
中间操作和
groupingBy
收集器,而不是
PartitionBy
,如下所示:

Map<Character, Long> result = "a simple sentence".chars()
                .mapToObj(c -> (char) c)
                .collect(groupingBy(Function.identity(),
                        counting()));
Map result=“一个简单的句子”.chars()
.mapToObj(c->(char)c)
.collect(groupingBy(Function.identity()),
计数());
或者,如果希望映射键为字符串,则可以执行以下操作:

Map<String, Long> result = "a simple sentence".chars()
                .mapToObj(c -> String.valueOf((char) c))
                .collect(groupingBy(Function.identity(),
                        counting()));
Map result=“一个简单的句子”.chars()
.mapToObj(c->String.valueOf((char)c))
.collect(groupingBy(Function.identity()),
计数());
或者,如果希望出现除空白字符以外的所有字符:

Map<String, Long> result = "a simple sentence".chars()
                .filter(c -> !Character.isSpaceChar(c))
                .mapToObj(c -> String.valueOf((char) c))
                .collect(groupingBy(Function.identity(),
                        counting()));
Map result=“一个简单的句子”.chars()
.filter(c->!Character.isSpaceChar(c))
.mapToObj(c->String.valueOf((char)c))
.collect(groupingBy(Function.identity()),
计数());
或使用模式:

Map<String, Long> result = 
     Pattern.compile("\\s+")
            .splitAsStream("a simple sentence")
            .flatMap(s -> Arrays.stream(s.split("")))
            .collect(groupingBy(Function.identity(),
                        counting()));
映射结果=
模式。编译(“\\s+”)
.splitAsStream(“一个简单的句子”)
.flatMap(s->array.stream(s.split(“”))
.collect(groupingBy(Function.identity()),
计数());
使用模式的更高效版本:

Map<String, Long> result = 
     Pattern.compile("") 
            .splitAsStream("a simple sentence")
            .filter(s -> !s.trim().isEmpty())
            .collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));
映射结果=
Pattern.compile(“”)
.splitAsStream(“一个简单的句子”)
.filter(s->!s.trim().isEmpty())
.collect(Collectors.groupingBy(Function.identity()、Collectors.counting());

c->c
可能是
Function.identity()
我更喜欢
c->c
而不是
Function.identity()
,因为它更短更干净。问题是什么?如果您的代码不起作用,请描述以何种方式?最后一种变体是浪费资源。为什么要将字符串拆分为单词字符串,然后再拆分(不一致地使用
string.split
)为字母字符串?为什么不首先使用
Pattern.compile(“”).splitAsStream(“一个简单的句子”)
。@Holger注意,特定的解决方案会从结果中删除空白字符。如果您建议使用
Pattern.compile(“”).splitAsStream(“一个简单的句子”).collect(Collectors.groupingBy(Function.identity(),Collectors.counting())然后这将保留空格字符,这不是我的意图。但是,可以简单地添加一个
过滤器
,在分组之前将其删除。。。与
.flatMap(s->Arrays.stream(s.split(“”))不同,
将是一种消除空白的巴洛克式解决方案(作为读者,我甚至不知道这是一个目标)。所以是的,我只需要使用
过滤器
。或者使用
Pattern.compile(“\\s+|)(?”?
Map<String, Long> result = 
     Pattern.compile("") 
            .splitAsStream("a simple sentence")
            .filter(s -> !s.trim().isEmpty())
            .collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));