Java 8 为IntStream生成直方图映射会引发编译时错误
我对构建哈夫曼编码原型感兴趣。为此,我想首先生成一个组成输入JavaJava 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&
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()));