I'm comparing two lists based on the following conditions:
If list1 has higher value,
1
to the first element in the result.If list2 has higher value,
1
to the second element in the result.If values are the same, skip it.
I have implemented this solution in Java 7
int min = a.size() > b.size() ? b.size() : a.size();
List<Integer> result = Arrays.asList(0, 0);
for(int i =0; i < min; i ) {
if(a.get(i) > b.get(i))
result.set(0, result.get(0) 1);
else if(a.get(i) < b.get(i))
result.set(1, result.get(1) 1);
}
return result;
How could I do the same with Java 8 streams?
I came up with two streams and merging the results of both. Because I am not sure how to do both the conditions in single streams.
CodePudding user response:
Using range()
method of the IntStream
we can create a stream of indices that are valid for these lists.
To filter out indices for which values are not equal, we can apply filter()
operation.
Accumulating the result in a list comprised of two elements will require a bit more effort. For that we can use collect(supplier,accumulator,combiner)
:
- supplier - a function that returns a new mutable container. Here we need to provide a list that should hold the results of reduction;
- accumulator - is a function defines the logic on how to add stream elements into the container;
- combiner - a function that defines how to merge the two containers with partial results obtained while executing the stream in parallel.
List<Integer> a = List.of(1, 2, 5);
List<Integer> b = List.of(1, 2, 8);
List<Integer> result = IntStream.range(0, Math.min(a.size(), b.size()))
.filter(i -> a.get(i) != b.get(i)) // filter out non-equal elements
.collect(
() -> Arrays.asList(0, 0), // supplier - provides a container which contain the results of reduction
(list, i) -> { // combiner - difines the logic on the container should be updated
if (a.get(i) > b.get(i)) list.set(0, list.get(0) 1);
else list.set(1, list.get(1) 1);
},
(left, right) -> { // accumulator - provides the logic for merging the two containers while executing in parallel
left.set(0, left.get(0) right.get(0));
left.set(1, left.get(1) right.get(1));
}
);
System.out.println(result);
Output:
[0, 1]
In case you doubt where it's a correct way to approach this problem with streams, have a look at the API documentation, paragraph Mutable reduction.
And even if after getting familiar with the reference above, you might think that it can be done without collect()
. For instance, why don't we simply apply filter().forEach()
to make the code leaner? Then have a look at another part of the API documentation, which is dedicated to Side-effects.