I have two lists.
List<Integer> list1 = new ArrayList<>(Arrays.asList(1, 2, 2));
List<Integer> list2 = new ArrayList<>(Arrays.asList(2, 3, 4));
I want to remove the elements contained in list2
from list1
, precisely as many times as they are contained in list2
. In the example above: when we remove elements in list 1 which exist in list 2, we should get as result [1, 2]
(only one occurrence of 2
should be removed from list1
because list2
contains only one instance of 2
).
I tried with list1.removeAll(list2);
but I got as result list containing only [1]
.
What is the best way to achieve this? Iterate through both lists simultaneous seems a bit ugly for me.
If I understand correctly, you only want to remove a single 2
element from list1
rather than all of them. You can iterate over list2
and attempt to remove each element from list1
. Keep in mind that there are more efficient methods than this if list2
cannot contain duplicates.
var list1 = new ArrayList<>(List.of(1, 2, 2));
var list2 = List.of(2, 3, 4);
list2.forEach(list1::remove);
list1
now contains the following:
[1, 2]
See starman1979's answer for the same solution, but using a lambda rather than a method reference.
How about:
list2.forEach(i -> {
list1.remove(i); //removes only first occurrence - if found
});
list1
now contains
[1, 2]
Given
List<Integer> a = new ArrayList<>(Arrays.asList(1, 2, 2));
List<Integer> b = Arrays.asList(2, 3, 4);
Use one of the following variants to get the desired result:
1. Plain java
b.forEach((i)->a.remove(i));
a
now contains
[1, 2]
Give credit at original post: add +1:
2. Apache Commons
In apache commons there is a subtract
method
Collection<Integer> result = CollectionUtils.subtract(a, b);
result
now contains
[1, 2]
Here is how they implemented it
3. Guava
Since guava doesn't offer a subtract
method you may find this advice from the google implementors helpful
"create an ArrayList containing a and then call remove on it for each element in b."
Which basically renders to what was already mentioned under 1.