Page 1 of 1

About Question enthuware.ocpjp.ii.v11.2.3330 :

Posted: Sat Nov 21, 2020 1:15 pm
by nirwan84
The last answer doesn't seem to be correct:

"var list2 = new ArrayList<String>();
listOfWords.parallelStream().forEach(s->{if(s.length()==2) list2.add(s); });
Observe that list2 is effectively final and so can be used in the lambda expression.
"
The ArrayList will potentially throw ConcurrentModificationException and therefore the: "will create a list of two letter words" is not true as it might create it or might not.

Re: About Question enthuware.ocpjp.ii.v11.2.3330 :

Posted: Sun Nov 22, 2020 11:33 am
by admin
Why do you think it may throw a ConcurrentModificationException ?

Re: About Question enthuware.ocpjp.ii.v11.2.3330 :

Posted: Sun Nov 22, 2020 3:03 pm
by nirwan84
Because forEach on parallelStream may be executed in "concurrent" way meaning that few threads will try to access and modify the ArrayList at the same time?

Actually it only happens while iterator is in play so it's all good.

Re: About Question enthuware.ocpjp.ii.v11.2.3330 :

Posted: Wed Jan 27, 2021 3:04 pm
by peterz
While it might not throw a ConcurrentModificationException, I think it is still problematic with respect to concurrency. The specification of forEach explicitly states that you must provide sufficient synchronization (which adding to a plain ArrayList does not):
For any given element, the action may be performed at whatever time and in whatever thread the library chooses. If the action accesses shared state, it is responsible for providing the required synchronization.

Re: About Question enthuware.ocpjp.ii.v11.2.3330 :

Posted: Wed Jan 27, 2021 9:52 pm
by admin
The issue in this case is only about the order of the words...i.e. the order is unpredictable. But the problem statement is not concerned with that. All it wants to do is to create a list of two letter words, which the given option satisfies.

Re: About Question enthuware.ocpjp.ii.v11.2.3330 :

Posted: Thu Jan 28, 2021 3:41 pm
by peterz
Well, the problem with concurrency bugs is that it will work most of the time. But it is not guaranteed that this will always work. If you have a long list this code is very likely to fail. For example the following code will fail on my machine after about 5 tries:

Code: Select all

    public static void main(String[] args) {
        List<String> listOfWords = Stream.generate(() -> "xx").limit(100000).collect(Collectors.toList());
        for (int i = 0;  ; i++) {
            System.out.println(i);
            var list2 = new ArrayList<String>();
            listOfWords.parallelStream().forEach(s->{if(s.length()==2) list2.add(s); });
        }
    }

Re: About Question enthuware.ocpjp.ii.v11.2.3330 :

Posted: Thu Jan 28, 2021 10:29 pm
by admin
You are right. The code inside forEach may be executed by different threads in case of parallelStream, thus list2 may be accessed by different threads and is therefore a shared variable.
The lambda expression has now been changed to :

Code: Select all

s->{if(s.length()==2) { synchronized(list2){list2.add(s);} } }
thank you for your feedback!

Re: About Question enthuware.ocpjp.ii.v11.2.3330 :

Posted: Mon Jun 19, 2023 9:16 pm
by namvh1506
var list2 = new ArrayList<String>();
listOfWords.parallelStream().forEach(s->{ if(s.length()==2) {
synchronized(list2){list2.add(s);} } } });

In this answer, there is one superfluous curly bracket.
Please check this, thank you.

Re: About Question enthuware.ocpjp.ii.v11.2.3330 :

Posted: Tue Jun 20, 2023 6:33 am
by admin
You are right. Fixed.
thank you for your feedback!