Java forEach()不应该尊重顺序,但在这里它似乎尊重,为什么?

Java forEach()不应该尊重顺序,但在这里它似乎尊重,为什么?,java,foreach,lambda,java-8,Java,Foreach,Lambda,Java 8,我一直在尝试自己做一些基本的GA实现。我使用了一个类Gene,它包装了一个二进制位,一个染色体类,它有一个数组列表名为genes的基因对象。在染色体类中,我有一个求值方法value(),它只计算染色体中位的十进制等价物。类中重写的toString()方法使用lambda表达式创建数组列表genes中包含的Gene对象中位的字符串表示。我的问题是:既然forEach()方法不应该尊重顺序(为了并行性的好处),为什么它总是返回底层位的正确字符串表示形式,即按照它们创建的顺序?还是我错过了什么重要的事

我一直在尝试自己做一些基本的GA实现。我使用了一个类
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太好了,你刚才在这上面加了盐;-)