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 should override equals and hashCode of your EPoint class, right now you are cheching if the object is the same. and the object is not the same, you can see it on the addresses of the object @6ef0145 -> the are all different
https://www.mkyong.com/java/java-how-to-overrides-equals-and-hashcode/
(sorry for the german link) http://www.tutego.de/javabuch/Java-ist-auch-eine-Insel/10/javainsel_08_003.html#dodtp848b6b5d-0c2d-464d-ac8e-4c765d194c9e
you should compare if long and lat are the same
If you just want to check for the presence of common elements, then you can make use of retainAll(Collection<?> c) method. Considering listAlpha and listBeta are two List<E>
List<T> commonItems = new ArrayList<>(listAlpha);
commonItems.retainAll(listBeta);
Now commonItems contains only those items that are common to listAplha and listBeta.
If you just need to test basic equality, this can be done with the basic JDK without modifying the input lists in the one line
!Collections.disjoint(list1, list2);
If you need to test a specific property, that's harder. I would recommend, by default,
list1.stream()
.map(Object1::getProperty)
.anyMatch(
list2.stream()
.map(Object2::getProperty)
.collect(toSet())
::contains)
...which collects the distinct values in list2 and tests each value in list1 for presence.
To shorten Narendra's logic, you can use this:
boolean var = list1.stream().anyMatch(element -> list2.contains(element));
Or even simpler
list1.stream().anyMatch(list2::contains);
When User is correctly defined with a hashCode and equals (otherwise you might try TreeSet instead of HashSet), do set-operations:
Set<User> common = new HashSet<>(a);
common.retainAll(b);
If User.getName is not used for equality:
Set<User> common = new TreeSet<>(Comparator.comparing(User::getName));
common.addAll(a);
common.retainAll(b);
Two nested for loops on lists (also as streams) would have complexity O(N²), whereas this is O(N.log N).
You can do something like below:
List<User> intersect = a.stream()
.filter(b::contains)
.collect(Collectors.toList());
You need to override equals and hashCode methods in User.
For optimization, you can convert b to HashSet first.
If you want to ignore the requirement of using a Set, you could use Java 8 Streams to solve the problem.
public static int numInCommon(List<Integer> list1, List<Integer> list2) {
return (int) list1.stream()
.distinct()
.filter(i -> list2.contains(i))
.count()
}
This is a four-step process:
- Get a stream of
list1(if you are not used to streams you can think of this as a loop, but in reality a call to.stream()by itself is not looping) - Use
.distinct()to ignore duplicate elements (that is, if the first list contains a number multiple times, it only processes it once. The.distinct()part uses aSetinternally to keep track of which elements it has seen. - Use
.filterto only keep the numbers that also occur in the second list. .count()to count the number of seen elements. This returns alongwhich is why the entire result is typecast to aninthere.
It's not until you call .count() that the loop is actually performed, this is because .count() is a "terminal operation".
I would recommend to read more about Streams on Oracle's website
I personally would shorten this greatly:
public static int numInCommon(List<Integer> list1, List<Integer> list2){
if(list1.isEmpty() || list2.isEmpty()){
return 0;
}
Set<Integer> setCommon = new HashSet<>(list1);
setCommon.retainAll(list2);
return setCommon.size();
}
Returning 0 at the start is good, but no need for the else block on the If code. Next task is to calculate the common elements - putting list1 into the set removes duplicates and then retainAll removes anything that isn't in list2. This leaves everythin in list1 and list2 without duplicates. Returning the size() counts the elements.
For performance - I'm taking the major assumption that HashSet is one of the quickest ways to check if an item exists and handle removal.
You can transform the lists to sets, and then use Set.retainAll method for intersection between the different sets.
Once you intersect all sets, you are left with the common elements, and you can transform the resulting set back to a list.
You can use Set's intersection method offered by Guava, Here is a little example :
public <T> Set<T> intersection(List<T>... list) {
Set<T> result = Sets.newHashSet(list[0]);
for (List<T> numbers : list) {
result = Sets.intersection(result, Sets.newHashSet(numbers));
}
return result;
}
Hope that could help you
If you care about order, then just use the equals method:
list1.equals(list2)
From the javadoc:
Compares the specified object with this list for equality. Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements e1 and e2 are equal if (e1==null ? e2==null : e1.equals(e2)).) In other words, two lists are defined to be equal if they contain the same elements in the same order. This definition ensures that the equals method works properly across different implementations of the List interface.
If you want to check independent of order, you could copy all of the elements to Sets and use equals on the resulting Sets:
public static <T> boolean listEqualsIgnoreOrder(List<T> list1, List<T> list2) {
return new HashSet<>(list1).equals(new HashSet<>(list2));
}
A limitation of this approach is that it not only ignores order, but also frequency of duplicate elements. For example, if list1 was ["A", "B", "A"] and list2 was ["A", "B", "B"] the Set approach would consider them to be equal.
If you need to be insensitive to order but sensitive to the frequency of duplicates you can either:
- sort both lists (or copies) before comparing them, as done in this answer to another question
- or copy all elements to a Multiset
I posted a bunch of stuff in comments I think it warrants its own answer.
As everyone says here, using equals() depends on the order. If you don't care about order, you have 3 options.
Option 1
Use containsAll(). This option is not ideal, in my opinion, because it offers worst case performance, O(n^2).
Option 2
There are two variations to this:
2a) If you don't care about maintaining the order ofyour lists... use Collections.sort() on both list. Then use the equals(). This is O(nlogn), because you do two sorts, and then an O(n) comparison.
2b) If you need to maintain the lists' order, you can copy both lists first. THEN you can use solution 2a on both the copied lists. However this might be unattractive if copying is very expensive.
This leads to:
Option 3
If your requirements are the same as part 2b, but copying is too expensive. You can use a TreeSet to do the sorting for you. Dump each list into its own TreeSet. It will be sorted in the set, and the original lists will remain intact. Then perform an equals() comparison on both TreeSets. The TreeSetss can be built in O(nlogn) time, and the equals() is O(n).
Take your pick :-).
EDIT: I almost forgot the same caveat that Laurence Gonsalves points out. The TreeSet implementation will eliminate duplicates. If you care about duplicates, you will need some sort of sorted multiset.