Reputation: 17602
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
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.
Upvotes: 0
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
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