Sнаđошƒаӽ
Sнаđошƒаӽ

Reputation: 17602

forEach() is not supposed to respect ordering, but here it seems to respect, why?

I have been trying to do a little basic GA implementation myself. I used a class Gene which wraps a binary bit, a Chromosome class that has an ArrayList named genes of Gene objects. In the Chromosome class I have an evaluation method value() that simply computes the decimal equivalent of the bits in the chromosome. The overridden toString() method in Chromosome class uses a lambda expression to create a String representation of the bits in the Gene objects contained in the ArrayList genes. My question is: since forEach() method is not supposed to respect the ordering (for the benefit of parallelism), why does it always return the correct string representation of the underlying bits, i.e. in the order in which they were created? Or am I missing something serious here? May it be because of very short chromosome length, that the 'disrespecting' of the ordering is not prominent here?

Here are my classes.

The Gene class

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);
    }
}

The Chromosome class

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);
    }
}

The print statement in Gene constructor is to see the order in which the genes were created. No matter how many times I run the program, the forEach() always gives the correct representation of the bits, which is confusing for me. Or am I completely ignorant of how this is supposed to work, I know not :-(

Upvotes: 2

Views: 193

Answers (3)

Sнаđошƒаӽ
Sнаđошƒаӽ

Reputation: 17602

Excellent answers given! But I would like to add this for future readers, as I found this stated very clearly in the link given by bajada93.

When you create a stream, it is always a serial stream unless otherwise specified. To create a parallel stream, invoke the operation Collection.parallelStream.

Which means forEach will iterate such collection in the order it was constructed.

Link: JavaSE tutorial

Upvotes: 0

Eran
Eran

Reputation: 393906

Since you are using a sequential Stream, the order of the input list is preserved. If you change it to

genes.parallelStream().forEach((g) -> chromosome.append(g));

You would probably get a different order.

Upvotes: 2

Luke Bajada
Luke Bajada

Reputation: 1852

Since genes is an ArrayList, and a List is ordered, you are basically printing the List according to how you added the stuff to it. Basically, the first to be printed is the first that was inputted.

If it was a parallelStream, the order would be random.

Takes a look at this link which explains the forEach in an excellent way.

Upvotes: 1

Related Questions