kukudas
kukudas

Reputation: 4934

Java 8 Stream modifying mutable var

I'm trying to understand how parallelStreams works. Lets consider the following example:

public class Person {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }  
    }

And a main method:

public static void main(String[] args) {
    final Person person = new Person();
    person.setName("John Doe");
    List<String> myList = Arrays.asList("1","2","3","4","5","6");
    myList.forEach((String element) -> {
        person.setName(person.getName()+element);
        System.out.println(person.getName());
    });
}

The result will be:

John Doe1
John Doe12
John Doe123
John Doe1234
John Doe12345
John Doe123456 

If i change it to parallelStream() the result could be like this:

John Doe4
John Doe41
John Doe415
John Doe4156
John Doe41562
John Doe415623  

Is it possible that less then 6 digits will be appended? For example if two Threads would read the value John Doe at the same time in the beginning. One Thread appends a "1" and the other Thread a "2". When setting the name again one of those would override the other.

Edit:

The reason why i asked: I have a String with some placeholders in it. I wrote my own Spliterator which extracts the placeholders. Furthermore i have a map which provides the replacements for the placeholders. So i apply a filter which checks if each placeholder has a replacement. After that i replace the String. I think replacing the String in the last step will not work correct if it is run in parallel mode.

Upvotes: 1

Views: 293

Answers (1)

Tunaki
Tunaki

Reputation: 137229

Yes this is possible. You just need to add more elements in the Stream to make it happen more often.

Consider this:

public static void main(String[] args) {
    final Person person = new Person();
    person.setName("John Doe");
    List<String> myList = IntStream.rangeClosed('a', 'z').mapToObj(c -> String.valueOf((char) c)).collect(Collectors.toList());
    myList.parallelStream().forEach((String element) -> {
        person.setName(person.getName()+element);
        System.out.println(person.getName());
    });
}

which the same as your code but this time we append all the lowercase letters in the alphabet. I just ran it and the last results where:

John Doengopqrswxyztuvabchijkl
John Doengopqrswxyztuvabchijklm
John Doengopqrswxyztuvabcd
John Doengopqrswxyztuvabcde
John Doengopqrswxyztuvabcdef

which means the effect you are describing is definitely happening.

The reason we need to add more elements is just to increase the probability that this effect will happen.


Important note: you haven't said in your question why you wanted this. But remember that mutating external variables is generally something you want to avoid in the first place.

Upvotes: 3

Related Questions