Jas*_*son 3 grouping histogram aggregation java-8 java-stream
我对构建霍夫曼编码原型感兴趣。为此,我想首先生成组成输入 Java 的字符的直方图String。我已经在 SO 和其他地方看到了许多解决方案(例如:这里依赖于使用s的collect()方法Stream以及以非常具体和直观的方式使用Function.identity()和 的静态导入Collectors.counting()。
但是,当使用一段与我上面链接的代码非常相似的代码时:
private List<HuffmanTrieNode> getCharsAndFreqs(String s){
Map<Character, Long> freqs = s.chars().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
return null;
}
Run Code Online (Sandbox Code Playgroud)
我从 Intellij 收到一个编译时错误,它基本上告诉我没有collect符合Supplier类型的参数,如其签名所要求的:
不幸的是,我是 Java 8Stream层次结构的新手,我不完全确定对我来说最好的行动方案应该是什么。事实上,Map对于我正在尝试做的事情来说,走这条路可能太多了;如果是这样,请告知。
问题是s.chars()返回一个IntStream- 一个特殊的特化Stream并且它没有一个collect接受单个参数的;它collect需要 3 个参数。显然,您可以使用boxed,这会将其转换IntStream为Stream<Integer>.
Map<Integer, Long> map = yourString.codePoints()
.boxed()
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting()));
Run Code Online (Sandbox Code Playgroud)
但现在的问题是你已经计数了code-points而不是字符。如果您完全知道您的 String 是由BMP 中的字符组成的,您可以安全地转换char为如另一个答案所示。如果你不是 - 事情变得更加棘手。
在这种情况下,您需要将单个 unicode 代码点作为字符获取 - 但它可能不适合Java char- 有 2 个字节;一个 unicode 字符最多可以有 4 个字节。
在这种情况下,您的地图应该是Map<String, Long>而不是Map<Character, Long>。
在 java-9 中引入了受支持的\X(和Scanner#findAll),这很容易做到:
String sample = "A" + "\uD835\uDD0A" + "B" + "C";
Map<String, Long> map = scan.findAll("\\X")
.map(MatchResult::group)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(map); // {A=1, B=1, C=1, =1}
Run Code Online (Sandbox Code Playgroud)
在 java-8 中,这会更冗长:
String sample = "AA" + "\uD835\uDD0A" + "B" + "C";
Map<String, Long> map = new HashMap<>();
Pattern p = Pattern.compile("\\P{M}\\p{M}*+");
Matcher m = p.matcher(sample);
while (m.find()) {
map.merge(m.group(), 1L, Long::sum);
}
System.out.println(map); // {A=2, B=1, C=1, =1}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1314 次 |
| 最近记录: |