Use Collection#retainAll().
listA.retainAll(listB);
// listA now contains only the elements which are also contained in listB.
If you want to avoid that changes are being affected in listA, then you need to create a new one.
List<Integer> common = new ArrayList<>(listA);
common.retainAll(listB);
// common now contains only the elements which are contained in listA and listB.
If you're a fan of streams, best what you could do is to Stream#filter() on Collection#contains() of the other list.
List<Integer> common = listA.stream().filter(listB::contains).toList();
// common now contains only the elements which are contained in listA and listB.
It's only at least twice slower.
Answer from BalusC on Stack OverflowUse Collection#retainAll().
listA.retainAll(listB);
// listA now contains only the elements which are also contained in listB.
If you want to avoid that changes are being affected in listA, then you need to create a new one.
List<Integer> common = new ArrayList<>(listA);
common.retainAll(listB);
// common now contains only the elements which are contained in listA and listB.
If you're a fan of streams, best what you could do is to Stream#filter() on Collection#contains() of the other list.
List<Integer> common = listA.stream().filter(listB::contains).toList();
// common now contains only the elements which are contained in listA and listB.
It's only at least twice slower.
You can use set intersection operations with your ArrayList objects.
Something like this:
List<Integer> l1 = new ArrayList<Integer>();
l1.add(1);
l1.add(2);
l1.add(3);
List<Integer> l2= new ArrayList<Integer>();
l2.add(4);
l2.add(2);
l2.add(3);
System.out.println("l1 == "+l1);
System.out.println("l2 == "+l2);
List<Integer> l3 = new ArrayList<Integer>(l2);
l3.retainAll(l1);
System.out.println("l3 == "+l3);
Now, l3 should have only common elements between l1 and l2.
CONSOLE OUTPUT
l1 == [1, 2, 3]
l2 == [4, 2, 3]
l3 == [2, 3]
You want intersection of the list while saving of first list type.
Get the common field values in the Set.
valuesToCheck=secondList.stream().map(SecondListObject::commonFiled).collect(Collectors.toList);
'''
Apply a stream on the first while filtering based on the matching common field value in the set built in the previous step.
firstList.stream().filter(x->valuesToCheck.contains(x.getCommonFiled)).collect(toList)
You got the gist.
Here is one possible solution. (Not tested.)
Assuming that the lists are are random access and the same length, and that neither the list elements or the properties are null:
List<SomeType> list1 = ...
List<SomeType> list2 = ...
List<SomeType> res =
IntStream.range(0, list1.size())
.filter(i -> list1.get(i).getSomeProp().equals(list2.get(i).getSomeProp()))
.map(i -> list1.get(i))
.Collectors.toList();
(This will also work if the lists aren't random access, but it will be O(N^2).)
I don't know of any cleaner way than what you already suggest.
However, if you need equality but can't use equals (I'm not going to ask ;) you could merge the lists and sort them, and then compare manually each element to the next, keeping only the duplicate ones.
If you want to get the same value from two list, I give you a string example:
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// create a script engine manager
List<String> list_1 = new ArrayList<String>();
list_1.add("a");
list_1.add("b");
List<String> list_2 = new ArrayList<String>();
list_2.add("a");
list_2.add("b");
list_2.add("c");
System.out.println(getSameVaue(list_2,list_1));
}
public static List<String> getSameVaue(List<String> list1,
List<String> list2) {
List<String> result = new ArrayList<String>();
if (list1.size() > list2.size()) {
for (String s : list1) {
if (list2.contains(s)) {
result.add(s);
}
}
} else {
for (String s : list2) {
if (list1.contains(s)) {
result.add(s);
}
}
}
return result;
}
But if you want to use your Object, please do not forget implement equals method.
If I understand correctly, this is the example scenario:
- listOne [datab] items:
[A, B, C, D] - listTwo [front] items:
[B, C, D, E, F]
and what you need to get as an effect is:
- added:
[E, F] - deleted:
[A]
First thing first, I would use some type adapter or extend the different types from one common class and override the equals method so you can match them by id and name
Secondly, this is very easy operations on sets (you could use set's but list are fine too). I recommend using a library: https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html
And now basically:
- added is
listTwo - listOne - deleted is
listOne - listTwo
and using java code:
- added:
CollectionUtils.removeAll(listTwo, listOne) - deleted:
CollectionUtils.removeAll(listOne, listTwo)
Otherwise, all collections implementing Collection (Java Docs) also has removeAll method, which you can use.
I propose solution using java 8 streams:
ArrayList<ObjOne> list = new ArrayList<>(Arrays.asList(new ObjOne("1","1"),new ObjOne("3","3"),new ObjOne("2","2")));
ArrayList<ObjTwo> list2 = new ArrayList<>(Arrays.asList(new ObjTwo("1","1"),new ObjTwo("3","3"),new ObjTwo("4","4")));
List<ObjOne> removed = list.stream().filter(o1 -> list2.stream().noneMatch(o2 -> o2.getId().equals(o1.getId())))
.collect(Collectors.toList());
System.out.print("added ");
removed.forEach(System.out::println);
List<ObjTwo> added = list2.stream().filter(o1 -> list.stream().noneMatch(o2 -> o2.getId().equals(o1.getId())))
.collect(Collectors.toList());
System.out.print("removed ");
added.forEach(System.out::println);
This is basically your solution but implemented using streams, which will make your code shorter and easer to read