为什么Java 8流(stream)元素无法按顺序访问?

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

Why are Java 8 stream elements not being accessed sequentially?

问题

我创建了一段代码,它读取一个字符串并创建出频率映射。我是在Java 8中提出的这个想法。

```java
final Map<Character, Integer> frequencyMap = new HashMap<>(26);
myString.chars()
    .forEach(ch -> frequencyMap.put((char)ch, frequencyMap.getOrDefault(ch, 0) + 1)); 

然而,我的输出结果如下 -

[1, 1, 1, 1, 1, 1, 1, 1]

我理解Lambda函数只能访问它作用域外部的final/实际上的final变量,但在这里我似乎也没有违反这个规则。
我尝试通过显式地使流变成顺序流来解决这个问题,但仍然不起作用。

str.chars()
    .sequential().forEach(ch -> frequencyMap.put((char)ch, frequencyMap.getOrDefault(ch, 0) + 1));

为了确保我在使用Map函数时没有问题,我尝试了相同的Map函数与数组,它可以工作 -

final Map<Character, Integer> frequencyMap = new HashMap<>(26);
for (char ch: str.toCharArray()) {
  frequencyMap.put((char)ch, frequencyMap.getOrDefault(ch, 0) + 1);
}

这里的输出结果 -

[1, 1, 1, 1, 1, 2, 3, 4]

我知道存在许多不同的解决方案来执行这个操作,但我对于我漏掉了哪个概念很感兴趣。


<details>
<summary>英文:</summary>

I created a piece of code which reads a String &amp; creates a frequency map out of it. I came up with this in Java 8.

final Map<Character, Integer> frequencyMap = new HashMap<>(26);
myString.chars()
.forEach(ch -> frequencyMap.put((char)ch, frequencyMap.getOrDefault(ch, 0) + 1));

However my output is as follows -

[1, 1, 1, 1, 1, 1, 1, 1]

I understand that the lambda functions can access only final/effectively final variables outside it&#39;s scope but here I don&#39;t seem to violate that rule as well.
I tried making the stream sequential explicitly by doing this but it still doesn&#39;t work

str.chars()
.sequential().forEach(ch -> frequencyMap.put((char)ch, frequencyMap.getOrDefault(ch, 0) + 1));

To be sure that there isn&#39;t a problem with the way I&#39;m using Map functions I tried the same map functions with array &amp; it works - 

final Map<Character, Integer> frequencyMap = new HashMap<>(26);
for (char ch: str.toCharArray()) {
frequencyMap.put((char)ch, frequencyMap.getOrDefault(ch, 0) + 1);
}

Output here - 

[1, 1, 1, 1, 1, 2, 3, 4]


I&#39;m aware of the many different solutions that exist to do this but I&#39;m interested in knowing what concept I&#39;m missing here?

</details>


# 答案1
**得分**: 2

你的想法是正确的。如果你还将`ch`转换为`char`,你的初始代码就能够工作:

```java
final Map<Character, Integer> frequencyMap = new HashMap<>(26);
myString.chars()
    .forEach(ch -> frequencyMap.put((char)ch, frequencyMap.getOrDefault((char)ch, 0) + 1));

如果你省略这个步骤,映射的键会是java.lang.Character类型。搜索键是java.lang.Integer类型,因此它们不相等。这会导致计数始终保持为1。

英文:

You had the right idea. Your initial code works if you also cast ch to char:

final Map&lt;Character, Integer&gt; frequencyMap = new HashMap&lt;&gt;(26);
    myString.chars()
        .forEach(ch -&gt; frequencyMap.put((char)ch, frequencyMap.getOrDefault((char)ch, 0) + 1));

If you omit this, the map key is a java.lang.Character. The search key is a java.lang.Integer and therefore they are not equal. This causes the count to stay 1 always.

答案2

得分: 0

试试这个。

Map<Character, Integer> frequencyMap = new HashMap<>(26);
myString.chars()
    .forEach(ch -> frequencyMap.compute((char)ch, (k, v) -> v == null ? 1 : v + 1));

或者

Map<Character, Integer> frequencyMap = myString.chars()
    .mapToObj(i -> (char)i)
    .collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(e -> 1)));

或者

Map<Character, Long> frequencyMap = myString.chars()
    .mapToObj(i -> (char)i)
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
英文:

Try this.

Map&lt;Character, Integer&gt; frequencyMap = new HashMap&lt;&gt;(26);
myString.chars()
    .forEach(ch -&gt; frequencyMap.compute((char)ch, (k, v) -&gt; v == null ? 1 : v + 1));

Or

Map&lt;Character, Integer&gt; frequencyMap = myString.chars()
    .mapToObj(i -&gt; (char)i)
    .collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(e -&gt; 1)));

Or

Map&lt;Character, Long&gt; frequencyMap = myString.chars()
    .mapToObj(i -&gt; (char)i)
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

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

发表评论

匿名网友

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

确定