Java forEach()不应该尊重顺序,但在这里它似乎尊重,为什么?
我一直在尝试自己做一些基本的GA实现。我使用了一个类Java forEach()不应该尊重顺序,但在这里它似乎尊重,为什么?,java,foreach,lambda,java-8,Java,Foreach,Lambda,Java 8,我一直在尝试自己做一些基本的GA实现。我使用了一个类Gene,它包装了一个二进制位,一个染色体类,它有一个数组列表名为genes的基因对象。在染色体类中,我有一个求值方法value(),它只计算染色体中位的十进制等价物。类中重写的toString()方法使用lambda表达式创建数组列表genes中包含的Gene对象中位的字符串表示。我的问题是:既然forEach()方法不应该尊重顺序(为了并行性的好处),为什么它总是返回底层位的正确字符串表示形式,即按照它们创建的顺序?还是我错过了什么重要的事
Gene
,它包装了一个二进制位,一个染色体
类,它有一个数组列表
名为genes
的基因
对象。在染色体
类中,我有一个求值方法value()
,它只计算染色体中位的十进制等价物。类中重写的toString()
方法使用lambda表达式创建数组列表genes
中包含的Gene
对象中位的字符串表示。我的问题是:既然forEach()
方法不应该尊重顺序(为了并行性的好处),为什么它总是返回底层位的正确字符串表示形式,即按照它们创建的顺序?还是我错过了什么重要的事情?可能是因为染色体长度很短,所以排序的“不尊重”在这里并不突出
这是我的课
基因
类
public class Gene {
private short value;
public Gene() {
value = (short) (Math.random() <= 0.5 ? 0 : 1);
System.out.print(value);
}
@Override
public String toString() {
return String.valueOf(value);
}
}
import java.util.ArrayList;
import java.util.Arrays;
public class Chromosome {
private ArrayList<Gene> genes;
public Chromosome(int numOfGene) {
this.genes = new ArrayList<>();
for (int i = 0; i < numOfGene; i++) {
this.genes.add(i, new Gene());
}
}
public int value() {
return Integer.parseInt(this.toString(), 2);
}
@Override
public String toString() {
StringBuilder chromosome = new StringBuilder("");
genes.stream().forEach((g) -> chromosome.append(g));
return chromosome.toString();
}
public static void main(String[] args) {
Chromosome c = new Chromosome(10);
System.out.println("");
System.out.println(c);
}
}
Gene
constructor中的print语句用于查看基因的创建顺序。无论我运行程序多少次,forEach()
总是给出正确的位表示,这让我感到困惑。或者我完全不知道这应该如何工作,我不知道:-(因为您使用的是顺序流,所以输入列表的顺序会保留。如果您将其更改为
genes.parallelStream().forEach((g) -> chromosome.append(g));
你可能会得到一个不同的顺序。因为基因是一个数组列表,一个列表是有序的,所以你基本上是根据你添加内容的方式来打印列表。基本上,第一个要打印的就是第一个输入的 如果它是并行流,则顺序将是随机的
看看这篇文章,它以一种极好的方式解释了forEach。给出了极好的答案!但我想为未来的读者补充一下,因为我在bajada93给出的链接中发现了这一点 创建流时,除非另有指定,否则它始终是串行流。若要创建并行流,请调用操作Collection.parallelStream 这意味着,
forEach
将按照该集合的构造顺序迭代该集合
而且,您可能不会。并行流上的
forEach
不能保证以任何特定顺序处理事情,但可能有一些实现不支持并行,它们可能只是按顺序处理所有事情。太好了!因此创建的任何流实际上都是串行流。要使其并行,需要使用parallelStream
。谢谢。我现在就知道了。请记住,并行流的存在是为了允许实现支持并行执行。但不支持并行执行的实现不需要特意按非顺序处理项。因此,一些实现在ons中,任何流操作都可以按顺序处理,即使不需要遵守顺序。当然,其他答案已经解释了为什么总是按顺序处理此流。请注意,惯用的方法是return genes.stream().map(Object::toString.collect())
@ajb太好了,你刚才在这上面加了盐;-)