说我有这个水果清单: -
List<String> f = Arrays.asList("Banana", "Apple", "Grape", "Orange", "Kiwi");
Run Code Online (Sandbox Code Playgroud)
我需要在每个水果前面加一个序列号并打印出来.水果或序列号的顺序无关紧要.所以这是一个有效的输出: -
4. Kiwi
3. Orange
1. Grape
2. Apple
5. Banana
Run Code Online (Sandbox Code Playgroud)
解决方案#1
AtomicInteger number = new AtomicInteger(0);
String result = f.parallelStream()
.map(i -> String.format("%d. %s", number.incrementAndGet(), i))
.collect(Collectors.joining("\n"));
Run Code Online (Sandbox Code Playgroud)
解决方案#2
String result = IntStream.rangeClosed(1, f.size())
.parallel()
.mapToObj(i -> String.format("%d. %s", i, f.get(i - 1)))
.collect(Collectors.joining("\n"));
Run Code Online (Sandbox Code Playgroud)
题
为什么解决方案#1是一种不好的做法?我在很多地方已经看到AtomicInteger
基础解决方案很糟糕(比如在这个答案中),特别是在并行流处理中(这就是我使用上面的并行流来尝试遇到问题的原因).
我查看了这些问题/答案: -
在哪些情况下,Stream操作应该是有状态的?
使用AtomicInteger在Stream中进行索引是一种合法的方式吗?
Java 8:计算lambda迭代的首选方法?
他们只是提到(除非我错过了什么)"可能会出现意想不到的结果".像什么?它可以在这个例子中发生吗?如果没有,你能为我提供一个可能发生的例子吗?
至于" 不保证应用映射器函数的顺序 ",那么这就是并行处理的本质,所以我接受它,而且,在这个特定的例子中,顺序无关紧要.
AtomicInteger
是线程安全的,所以它不应该是并行处理的问题.
有人可以提供使用这种基于状态的解决方案时会出现问题的示例吗?
我试图在循环中实现一个内部类,并进入一个有趣的情况.内部类有方法,但是,当我尝试访问变量时,Netbeans给了我一个编译错误并告诉我让int最终.
由于int是循环变量,因此它不能是最终的.我已经尝试创建新变量并将它们等同于循环变量,但这仍然会引发相同的错误.
这是基本语法(伪代码):
for(int i = 0; i < 10; i++)
{
panels[i].printI(new printI(){System.out.println(i);});
}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?