Java 8 为IntStream生成直方图映射会引发编译时错误

Java 8 为IntStream生成直方图映射会引发编译时错误,java-8,grouping,histogram,java-stream,aggregation,Java 8,Grouping,Histogram,Java Stream,Aggregation,我对构建哈夫曼编码原型感兴趣。为此,我想首先生成一个组成输入JavaString的字符直方图。我在SO和其他地方看到了许多解决方案(例如:依赖于对流使用collect()方法,以及以非常具体和直观的方式静态导入Function.identity()和collector.counting()) 然而,当使用一段与我上面链接的代码非常相似的代码时: private List<HuffmanTrieNode> getCharsAndFreqs(String s){ Map&

我对构建哈夫曼编码原型感兴趣。为此,我想首先生成一个组成输入Java
String
的字符直方图。我在SO和其他地方看到了许多解决方案(例如:依赖于对
使用
collect()
方法,以及以非常具体和直观的方式静态导入
Function.identity()
collector.counting()

然而,当使用一段与我上面链接的代码非常相似的代码时:

private List<HuffmanTrieNode> getCharsAndFreqs(String s){
        Map<Character, Long> freqs = s.chars().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
        return null;
}
私有列表getCharsAndFreqs(字符串s){
Map freqs=s.chars().collect(Collectors.groupingBy(Function.identity(),Collectors.counting());
返回null;
}
我从Intellij收到一个编译时错误,它本质上告诉我,
collect
没有符合
供应商
类型的参数,如其签名所要求:

不幸的是,我对Java 8
层次结构还不熟悉,我不完全确定对我来说最好的做法应该是什么。事实上,按照
映射
的方式可能会让我尝试做的事情太繁琐;如果是这样,请给出建议。

字符串.chars()
方法返回一个
IntStream
。您可能希望通过以下方式将其转换为

s.chars().mapToObj(c -> (char)c)

如前所述,您可以将流转换为基本类型,再转换为对象类型

s.chars().boxed()
 .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

问题是
s.chars()
返回一个
IntStream
——一个
流的特殊特化,它没有一个
collect
接受一个参数;它是
collect
接受3个参数。显然,您可以使用
装箱的
来将
IntStream
转换为
Stream

Map Map=yourString.codePoints()
.boxed()
.collect(收集器.groupingBy(
Function.identity(),
收集器。计数();
但现在的问题是,您已经计算了
代码点而不是字符。如果您完全知道字符串是由中的字符组成的,您可以安全地转换为
char
,如另一个答案所示。如果您没有-事情会变得更棘手

在这种情况下,您需要将单个unicode代码点作为一个字符来获取,但它可能不适合具有2个字节的
Java char
;而unicode字符最多可以是4个字节

在这种情况下,地图应该是
map
,而不是
map

在java-9中,通过引入受支持的
\X
(和
Scanner#findAll
),这非常容易做到:

String sample=“A”+”\uD835\uDD0A”+“B”+“C”;
Map Map=scan.findAll(\\X)
.map(匹配结果::组)
.collect(Collectors.groupingBy(Function.identity()、Collectors.counting());

System.out.println(map);//{A=1,B=1,C=1,如果通过
codePoints()
创建的流将计数代码点而不是
char
s这一事实是一个问题,那么就使用
chars()
就像OP一样。你正在试图解决你自己造成的问题。@Holger-hmm。你可能是对的。因此,如果我想看到“人类可读字符”以及它重复了多少次,我可以简单地使用:
s.codePoints().mapToObj(x->新字符串(character.toChars(x))
a“人类可读字符”还有一件事。有
char
s,这16位的单位可以映射1:1或2:1到代码点,但是(人类可读的)字符甚至可能由多个代码点组成,如
U+0041 U+0308
,两者都在BMP中,因此重要的是不要混淆“
char
vs代码点”问题“代码点与字符(或字符集)”问题。您的最后两个示例分为多个字符,但如果您想打开那罐蠕虫,您必须注意,它们不知道哪些字符是相同的,例如,
U+0041 U+0308
U+00C4
相同……但请注意,OP似乎有意实现一种不需要考虑的压缩算法去掉语义,这样一个
char
值的直方图就足够了
Map<Integer, Long> map = yourString.codePoints()
          .boxed()
          .collect(Collectors.groupingBy(
                      Function.identity(), 
                      Collectors.counting()));