'How to compare the elements of an ArrayList with every element of another ArrayList using Stream API of Java 8?
I have two Sorted ArrayList of same size, namely team_A
& team_B
, in which comparing every element of team_A
with team_B
to find the powerDiff > 0
. After finding the powerDiff
greater than 0, then removing that element from the team_B
to reduce the number of iteration in the next cycle.
long calculateWin(){
int wins = 0;
int tempIndex=0;
boolean flag = false;
long powerDiff=0;
for(int i=0; i<team_A.size(); i++) {
for(int j=0; j<team_B.size(); j++) {
powerDiff = team_A.get(i) - team_B.get(j);
if(powerDiff>0) {
wins++;
tempIndex=j;
flag=true;
break;
}
}
if(flag) {
team_B.remove(tempIndex);
flag = false;
}
}
return wins;
}
The above code is working fine but due to complexity I want to optimize this code using the Stream API of Java 8.
Solution 1:[1]
Could you please try this one;
public static long calculateWinJava8(){
List<Long> team_A = new ArrayList(Arrays.asList(50L,60L,70L,80L,90L,100L));
List<Long> team_B = new ArrayList(Arrays.asList(30L,40L,25L,80L,55L,200L,250L));
int wins = team_B.size();
team_A.stream().forEach(itemA->{
List<Long> removeItems = team_B.stream().filter(itemB-> (itemA-itemB)>0).collect(Collectors.toList());
team_B.removeAll(removeItems);
});
System.out.println("result team_B : "+team_B.toString());
wins = wins - team_B.size();
System.out.println("wins : "+wins);
return 0;
}
Solution 2:[2]
There isn't a good way with the standard JDK because it's lacking basic constructs like a .zip() operator and a Tuple class. If it did it would look something like this:
val wins = team_a.zip(team_b)
.filter { tuple -> tuple.first > tuple.second }
.count()
That's kotlin but there are a ton of java libaries that offer a .zip() and Tuple.
If you really want to do it with just the JDK it'd be something like:
long wins = IntStream
.range(0, Math.min(team_a.size(), team_b.size()))
.filter(i -> team_a.get(i) > team_b.get(i))
.count();
This works but isn't ideal since you are reaching outside the pipeline unlike the first example.
Solution 3:[3]
Ok, let's untangle the logic a bit.
You check for for each pair if a[i] > b[j]. And if it matches, you remove b[j].
Good. long
has a total order, so, we only need it's maximum.
long max_a = team_a.stream().mapToLong(a -> a).max().getAsLong();
Now that we have the most powerful of team a, we check how many they can defeat:
long wins = team_b.stream().filter(b -> a > b).count();
And that's it.
Wait. I did not notice the key word "sorted" in your question.
This means we can do a binary search.
First we get the maximum. I assume the list are in ascending order.
long max_a = team_a.get(team_a.size()-1);
Now we need to find where we have to make the cut:
int idx = Collections.binarySearch(team_b, max_a);
Note that Collections.binarySearch
can return a negative number if the maximum is not in the list. But we are only interested in the number of smaller items in the list.
if (idx < 0)
idx = -idx - 1
Now idx
contains the number of elements smaller than the largest element in the first list. Return that:
return idx;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | KEYSAN |
Solution 2 | |
Solution 3 |