About Question enthuware.ocpjp.v8.2.1791 :

Help and support on OCA OCP Java Programmer Certification Questions
1Z0-808, 1Z0-809, 1Z0-815, 1Z0-816, 1Z0-817

Moderator: admin

Post Reply
pushpa
Posts: 7
Joined: Thu Apr 28, 2016 4:59 am
Contact:

About Question enthuware.ocpjp.v8.2.1791 :

Post by pushpa »

Code: Select all

List<String> vals = Arrays.asList("a", "b"); String join = vals.parallelStream()         .reduce("_",                 (a, b)->a.concat(b)                 ); System.out.println(join);

Should not the output be always _a_b.

Can you please explain how can we get _ab?

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by admin »

Why do you think it should _a_b?
If you like our products and services, please help us by posting your review here.

pushpa
Posts: 7
Joined: Thu Apr 28, 2016 4:59 am
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by pushpa »

Because I tried running the program and I always get _a_b even after introducing thread sleeps. Now if you could tell me how to get _ab?

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by admin »

Just change the call to parallelStream to stream and you will see that it will print _ab. Now, the point is that even when you use parallelStream, there is no guarantee that elements will be processed in parallel. If you have a single core machine, it is possible that you get a serial stream.
That is why you cannot guarantee that the result will always be _a_b.
HTH,
Paul.
If you like our products and services, please help us by posting your review here.

pushpa
Posts: 7
Joined: Thu Apr 28, 2016 4:59 am
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by pushpa »

Got _ab with stream. But whether its a parallelStream or stream output should be same write. One cannot get different output when trying to use parallelStream for performance. I found the right explanation its the violation of identity contract by reduce method. With parallel stream its always _a_b. Thanks anyway !!

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by admin »

pushpa wrote:Got _ab with stream. But whether its a parallelStream or stream output should be same write. One cannot get different output when trying to use parallelStream for performance.
If your identity function is indeed an identity function (i.e. it doesn't change the value to which it is applied). Here, it is not.
I found the right explanation its the violation of identity contract by reduce method. With parallel stream its always _a_b. Thanks anyway !!
No, the given code will not produce _a_b always for parallelStream precisely as explained above. If you disagree please quote your source so that others will be benefited.

HTH,
Paul.
If you like our products and services, please help us by posting your review here.

pushpa
Posts: 7
Joined: Thu Apr 28, 2016 4:59 am
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by pushpa »

import java.util.*;
import java.util.stream.*;

class TestParallelStream{


public static void main(String args[]){


List<String> l = Arrays.asList("a","b","c","d");
String join=l.stream()
.peek(TestParallelStream::sleepFor)
.reduce("_",(a,b) -> a.concat(b));
System.out.println(join);


}



public static void sleepFor(String w)

{
System.out.println("inside thread:"+w);
try{
Thread.currentThread().sleep(5000);

}catch(InterruptedException e){

}
}
}

Here is the code. I tried for both parallelStream and Stream. For parallelStream always _a_b and for stream _ab.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by admin »

Did you even read the explanation I posted above?? What if this code is run on a single core machine?
If you like our products and services, please help us by posting your review here.

mtrikannad
Posts: 11
Joined: Mon Jan 18, 2016 4:35 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by mtrikannad »

I have just returned after writing the test. There was a question similar to this one, however the only choice that seemed to make sense was a choice that said _ab. The others choices that had _a_b also had _b_a ( Which make them incorrect since reduce maintains the order ).

As per your explanation the output would not be guaranteed to be _ab. I think I got it right though ( _ab ) because my exam results indicated I didnt get anything wrong on this topic.

In any case the good news is that I passed with 80% thanks to Enthuware :)

aaaqwert
Posts: 7
Joined: Mon Jul 11, 2016 12:08 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by aaaqwert »

Hello.
Could you please provide a link to javadoc (or language specification) which is supposed to prove this part of explanation:
Even though the elements may be processed out of order individualy in different threads, the final output will be produced by joining the individual reduction results in the same order. Thus, the output can never have b before a.
It is quite logical for me but I didn't find it in javadoc and just what be sure that it is not an implementation detail and is guaranteed across different versions of JVM.

Thank you.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by admin »

It is not mentioned directly but is quite clear from the discussion about "ordering" given here: http://docs.oracle.com/javase/8/docs/ap ... l#Ordering
Streams may or may not have a defined encounter order. Whether or not a stream has an encounter order depends on the source and the intermediate operations. Certain stream sources (such as List or arrays) are intrinsically ordered, whereas others (such as HashSet) are not. Some intermediate operations, such as sorted(), may impose an encounter order on an otherwise unordered stream, and others may render an ordered stream unordered, such as BaseStream.unordered(). Further, some terminal operations may ignore encounter order, such as forEach().

If a stream is ordered, most operations are constrained to operate on the elements in their encounter order; if the source of a stream is a List containing [1, 2, 3], then the result of executing map(x -> x*2) must be [2, 4, 6]. However, if the source has no defined encounter order, then any permutation of the values [2, 4, 6] would be a valid result.
HTH,
Paul.
If you like our products and services, please help us by posting your review here.

safdev
Posts: 5
Joined: Wed May 24, 2017 5:17 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by safdev »

admin wrote:Just change the call to parallelStream to stream and you will see that it will print _ab. Now, the point is that even when you use parallelStream, there is no guarantee that elements will be processed in parallel. If you have a single core machine, it is possible that you get a serial stream.
That is why you cannot guarantee that the result will always be _a_b.
HTH,
Paul.
I still don't understand how it could return _ab.

I am trying to differentiate between two things:
1. Processing a parallel stream in a sequential manner (no matter how many threads are available)
2. Processing a parallel stream using a single thread (which follows different steps than those of a sequential operation)

In other words, I am trying not to confuse a "sequential operation" with a"parallel operation with a single thread". In the case of reduce() for example, I believe that in case of a parallel stream the identity is accumulated with every element first producing intermediate results, then the combiner combines those results to produce the final output. This has nothing to do with the number of threads available, parallel evaluation follows different steps in the first place. Even if there is only on thread, it will follow the same steps (that is, compute the intermediate accumulations then combine them). On the other hand, in case of a sequential stream, reduce() follows a different logic; it doesn't invoke the combiner at all (since there are no intermediate results). Both parallel and sequential reductions are supposed to give the same output, provided some criteria are met (which is not the case in this question).

To verify such point, I changed the example given in the explanation of the question to use a custom ForkJoinPool with only one thread to process the parallel stream (ForkJoinPool.commonPool() is used by parallel streams). It gave me an output consistent with my point. The code is in the following post due to the character count limit.

safdev
Posts: 5
Joined: Wed May 24, 2017 5:17 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by safdev »

Code: Select all

ForkJoinPool customPool = new ForkJoinPool(1);     // only one thread that performs intermediate accumulations then combines
String join = null;
try {
	join = customPool.submit(() -> 
		Arrays.asList("a", "b", "c", "d", "e", "f", "g", "a", "b", "c", "d", "e", "f", "g", "a", "b", "c", "d", "e", "f", "g", "a", "b", "c", "d", "e", "f", "g")
			.parallelStream().peek(System.out::println) //this shows how the elements are retrieved from the stream
			.reduce("_", 
				(a, b)->{ System.out.println("reducing "+a+" and "+b+" Thread: "+Thread.currentThread().getName()); return a.concat(b); },
				(a, b)->{ System.out.println("combining "+a+" and "+b+" Thread: "+Thread.currentThread().getName()); return a.concat(b);}
		)).get();
} catch(ExecutionException | InterruptedException e) { 
	System.out.println(e);
}
System.out.println("Join = " + join); // _a_b_c_d_e_f_g_a_b_c_d_e_f_g_a_b_c_d_e_f_g_a_b_c_d_e_f_g

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by admin »

It looks like the your argument is based on, "I believe that in case of a parallel stream the identity is accumulated with every element first producing intermediate results, then the combiner combines those results to produce the final output."
I tried to check the JavaDoc as well as Oracle's official tutorial to see anything like this is mentioned but couldn't find anything.
I also executed the code you posted above and here is the output:

Code: Select all

d
reducing _ and d Thread: ForkJoinPool-1-worker-1
e
reducing _d and e Thread: ForkJoinPool-1-worker-1
f
reducing _ and f Thread: ForkJoinPool-1-worker-1
g
reducing _f and g Thread: ForkJoinPool-1-worker-1
combining _de and _fg Thread: ForkJoinPool-1-worker-1
b
reducing _ and b Thread: ForkJoinPool-1-worker-1
c
reducing _b and c Thread: ForkJoinPool-1-worker-1
a
reducing _ and a Thread: ForkJoinPool-1-worker-1
combining _a and _bc Thread: ForkJoinPool-1-worker-1
combining _a_bc and _de_fg Thread: ForkJoinPool-1-worker-1
d
reducing _ and d Thread: ForkJoinPool-1-worker-1
e
reducing _d and e Thread: ForkJoinPool-1-worker-1
f
reducing _ and f Thread: ForkJoinPool-1-worker-1
g
reducing _f and g Thread: ForkJoinPool-1-worker-1
combining _de and _fg Thread: ForkJoinPool-1-worker-1
b
reducing _ and b Thread: ForkJoinPool-1-worker-1
c
reducing _b and c Thread: ForkJoinPool-1-worker-1
a
reducing _ and a Thread: ForkJoinPool-1-worker-1
combining _a and _bc Thread: ForkJoinPool-1-worker-1
combining _a_bc and _de_fg Thread: ForkJoinPool-1-worker-1
combining _a_bc_de_fg and _a_bc_de_fg Thread: ForkJoinPool-1-worker-1
b
reducing _ and b Thread: ForkJoinPool-1-worker-1
c
reducing _b and c Thread: ForkJoinPool-1-worker-1
a
reducing _ and a Thread: ForkJoinPool-1-worker-1
combining _a and _bc Thread: ForkJoinPool-1-worker-1
f
reducing _ and f Thread: ForkJoinPool-1-worker-1
g
reducing _f and g Thread: ForkJoinPool-1-worker-1
d
reducing _ and d Thread: ForkJoinPool-1-worker-1
e
reducing _d and e Thread: ForkJoinPool-1-worker-1
combining _de and _fg Thread: ForkJoinPool-1-worker-1
combining _a_bc and _de_fg Thread: ForkJoinPool-1-worker-1
d
reducing _ and d Thread: ForkJoinPool-1-worker-1
e
reducing _d and e Thread: ForkJoinPool-1-worker-1
f
reducing _ and f Thread: ForkJoinPool-1-worker-1
g
reducing _f and g Thread: ForkJoinPool-1-worker-1
combining _de and _fg Thread: ForkJoinPool-1-worker-1
b
reducing _ and b Thread: ForkJoinPool-1-worker-1
c
reducing _b and c Thread: ForkJoinPool-1-worker-1
a
reducing _ and a Thread: ForkJoinPool-1-worker-1
combining _a and _bc Thread: ForkJoinPool-1-worker-1
combining _a_bc and _de_fg Thread: ForkJoinPool-1-worker-1
combining _a_bc_de_fg and _a_bc_de_fg Thread: ForkJoinPool-1-worker-1
combining _a_bc_de_fg_a_bc_de_fg and _a_bc_de_fg_a_bc_de_fg Thread: ForkJoinPool-1-worker-1
Join = _a_bc_de_fg_a_bc_de_fg_a_bc_de_fg_a_bc_de_fg
You will notice that not all elements have been first reduced with identity.
Paul.
If you like our products and services, please help us by posting your review here.

safdev
Posts: 5
Joined: Wed May 24, 2017 5:17 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by safdev »

Thanks Paul, I don't know why our outputs are different!
I thought about checking the source code to know the inner workings of parallel reduction (in ReferencePipeline & ReduceOps classes), but I don't seem to have much time :x ... my exam is next week. Wish me luck :cheers:

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by admin »

Looking at internal code is not a good idea because it can change. So even if the code works in the way you described (which is not the case as shown by the output I got), you can't rely on that because the API doesn't promise it. It might work differently in another version.

All the best :)
If you like our products and services, please help us by posting your review here.

crazymind
Posts: 85
Joined: Mon Dec 24, 2018 6:24 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by crazymind »

In this case, the identity argument will be used to reduce both the elements. Thus, it will print _a_b.
Is this true for all parallel stream? (identity will be used to reduce both the element? the combiner will combine these results together in order? In this case, no compiler is available)

Code: Select all

String join = vals.parallelStream().reduce("_", (a, b)->a.concat(b)); 
I also find that the identity is not true for "accumulator.apply(identity, t) is equal to t". This will make the output undeterminable.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by admin »

crazymind wrote:
Fri Feb 22, 2019 10:51 am
In this case, the identity argument will be used to reduce both the elements. Thus, it will print _a_b.
Is this true for all parallel stream? (identity will be used to reduce both the element? the combiner will combine these results together in order? In this case, no compiler is available)

Code: Select all

String join = vals.parallelStream().reduce("_", (a, b)->a.concat(b)); 
I also find that the identity is not true for "accumulator.apply(identity, t) is equal to t". This will make the output undeterminable.
No, the explanation is talking about one possibility. Read the first line of the explanation, "Since we are creating a parallel stream, it is possible for both the elements of the stream to be processed by two different threads. In this case, the identity argument will be used to reduce both the elements. "

Yes, two possibilities exist _ab and _a_b. Please read the explanation carefully and go through the above discussion.
If you like our products and services, please help us by posting your review here.

crazymind
Posts: 85
Joined: Mon Dec 24, 2018 6:24 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by crazymind »

admin wrote:
Fri Feb 22, 2019 8:32 pm
crazymind wrote:
Fri Feb 22, 2019 10:51 am
In this case, the identity argument will be used to reduce both the elements. Thus, it will print _a_b.
Is this true for all parallel stream? (identity will be used to reduce both the element? the combiner will combine these results together in order? In this case, no compiler is available)

Code: Select all

String join = vals.parallelStream().reduce("_", (a, b)->a.concat(b)); 
I also find that the identity is not true for "accumulator.apply(identity, t) is equal to t". This will make the output undeterminable.
No, the explanation is talking about one possibility. Read the first line of the explanation, "Since we are creating a parallel stream, it is possible for both the elements of the stream to be processed by two different threads. In this case, the identity argument will be used to reduce both the elements. "

Yes, two possibilities exist _ab and _a_b. Please read the explanation carefully and go through the above discussion.
Thanks. This reduce method does not provide a combiner. How does these two result combine together if two threads works parallel and produce "_a" and "_b" respectively?

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by admin »

You may read the details of this method here: https://docs.oracle.com/javase/8/docs/a ... yOperator-
If you like our products and services, please help us by posting your review here.

saurabh.agarwal560
Posts: 11
Joined: Thu May 28, 2020 9:53 am
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by saurabh.agarwal560 »

I still dont understand that if its parallelStream than any value i.e "a" / "b" can come first and can result in final reduction as _ba/_b_a/_ab/_a_b. Please explain why only "a" is coming as first element in parallel stream too.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1791 :

Post by admin »

Any element may be processed by the intermediate operations in any order. But the result will be joined in order. That is what the explanation also explains:
Even though the elements may be processed out of order individualy in different threads, the final output will be produced by joining the individual reduction results in the same order. Thus, the output can never have b before a.
If you like our products and services, please help us by posting your review here.

Post Reply

Who is online

Users browsing this forum: No registered users and 45 guests