将字符串收集到LinkedHashMap中,其中包含字符的频率。

huangapple go评论71阅读模式
英文:

Collect String to LinkedHashMap <Character, Integer> , with frequency of characters

问题

这是我修改后的代码:

private Map<Character, Integer> countSymbols(String sentence) {
    return sentence.chars()
            .mapToObj(c -> (char) c)
            .collect(Collectors.toMap(
                    Function.identity(),
                    c -> 1,
                    Integer::sum,
                    LinkedHashMap::new));
}
英文:

I need to collect a sentence to a map using stream, where the key is a character (the order should be like this: the first letter in the sentence is the first in the map, so I choose LinkedHashMap ), and the value is counter which shows the frequency of repeating the same character.
> Example input: hello world

> Example output: h=1 , e=1, l=3, o=2, w=1 , r=1, d=1

There is my code, and I can`t understand what is the problem.

private Map&lt;Character, Integer&gt; countSymbols(String sentence) {
    return sentence.chars()
            .collect(Collectors.toMap(key -&gt; (Character) key, 
                    counter -&gt; 1, 
                    Integer::sum, 
                    LinkedHashMap::new));
}

答案1

得分: 3

String.chars() 返回一个 IntStream,表示原始的 int 流,无法使用 Collectors.toMap 进行收集。

你可以将其映射为一个 Character 对象,一旦完成映射,你可以使用 Collectors.grouping 来完成繁重的工作,而不是实现它的逻辑:

private Map<Character, Long> countSymbols(String sentence) {
    return sentence.chars()
                    .mapToObj(c -> (char) c)
                    .collect(Collectors.groupingBy(Function.identity(), 
                                                   Collectors.counting()));
}

编辑:
Collectors.grouping 不保留流的顺序,所以你确实需要像你之前做的那样手动实现它。
mapToObj 调用仍然是必需的,如果你想避免在示例中 "hello" 和 "world" 之间计算空格,你需要添加一个 filter 调用:

private Map<Character, Integer> countSymbols(String sentence) {
    return sentence.chars()
                   .filter(Character::isAlphabetic)
                   .mapToObj(c -> (char) c)
                   .collect(Collectors.toMap(Function.identity(),
                            counter -> 1,
                            Integer::sum,
                            LinkedHashMap::new));
}
英文:

String.chars() returns an IntStream (i.e., a stream of primitieve ints), that can't be collected with Collectors.toMap.

You could map it to a Character object, and once you've done so, you could use Collectors.grouping to do the heavy lifting instead of implementing its logic:

private Map&lt;Character, Long&gt; countSymbols(String sentence) {
    return sentence.chars()
                    .mapToObj(c -&gt; (char) c)
                    .collect(Collectors.groupingBy(Function.identity(), 
                                                   Collectors.counting()));
}

EDIT:<br/>
Collectors.grouping does not retain the order of the stream, so you'll really have to implement it manually as you've done.
the mapToObj call is still required, and if you want to avoid counting the space between "hello" and "world" in the example, you need to add a filter call:

private Map&lt;Character, Integer&gt; countSymbols(String sentence) {
    return sentence.chars()
                   .filter(Character::isAlphabetic)
                   .mapToObj(c -&gt; (char) c)
                   .collect(Collectors.toMap(Function.identity(),
                            counter -&gt; 1,
                            Integer::sum,
                            LinkedHashMap::new));
}

huangapple
  • 本文由 发表于 2020年8月29日 20:58:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/63647219.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定