While working with a tree set, I found very peculiar behavior.
As per my understanding following program should print two identical lines:
public class TestSet {
static void test(String... args) {
Set<String> s = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
s.addAll(Arrays.asList("a", "b"));
s.removeAll(Arrays.asList(args));
System.out.println(s);
}
public static void main(String[] args) {
test("A");
test("A", "C");
}
}
but strangely it prints:
[b]
[a, b]
I am unable to understand - Why is tree set behaving like this?
This happens because a SortedSet’s Comparator is used for sorting, but removeAll relies on the equals method of each element. From the SortedSet documentation:
Note that the ordering maintained by a sorted set (whether or not an explicit comparator is provided) must be consistent with equals if the sorted set is to correctly implement the Set interface. (See the Comparable interface or Comparator interface for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a sorted set performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the sorted set, equal. The behavior of a sorted set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.
The explanation of “consistent with equals” is defined in the Comparable documentation:
The natural ordering for a class C is said to be consistent with equals if and only if e1.compareTo(e2) == 0 has the same boolean value as e1.equals(e2) for every e1 and e2 of class C. Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false.
It is strongly recommended (though not required) that natural orderings be consistent with equals. This is so because sorted sets (and sorted maps) without explicit comparators behave "strangely" when they are used with elements (or keys) whose natural ordering is inconsistent with equals. In particular, such a sorted set (or sorted map) violates the general contract for set (or map), which is defined in terms of the equals method.
In summary, your Set’s Comparator behaves differently than the elements’ equals method, causing unusual (though predictable) behavior.
Well, this surprised me, I don't know if I'm correct, but look at this implementation in AbstractSet:
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
if (size() > c.size()) {
for (Iterator<?> i = c.iterator(); i.hasNext(); )
modified |= remove(i.next());
} else {
for (Iterator<?> i = iterator(); i.hasNext(); ) {
if (c.contains(i.next())) {
i.remove();
modified = true;
}
}
}
return modified;
}
Basically in your example, the size of set is equal to the size of arguments you want to remove, so the else condition is invoked. In that condition there is a check if your collection of arguments to remove contains the current element of iterator, and that check is case sensitive, so it checks if c.contains("a") and it returns false, because c contains "A", not "a", so the element is not removed. Notice that when you add an element to your set s.addAll(Arrays.asList("a", "b", "d")); it works correctly, because size() > c.size() is now true, thus there is no contains check anymore.
To add some information about why the remove of TreeSet actually removes case-insensively in your example (and provided that you follow the if (size() > c.size()) path as explained in the answer by #Shadov) :
This is the removemethod in TreeSet :
public boolean remove(Object o) {
return m.remove(o)==PRESENT;
}
it calls remove from its internal TreeMap :
public V remove(Object key) {
Entry<K,V> p = getEntry(key);
if (p == null)
return null;
V oldValue = p.value;
deleteEntry(p);
return oldValue;
}
which calls getEntry
final Entry<K,V> getEntry(Object key) {
// Offload comparator-based version for sake of performance
if (comparator != null)
return getEntryUsingComparator(key);
if (key == null)
throw new NullPointerException();
#SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
Entry<K,V> p = root;
while (p != null) {
int cmp = k.compareTo(p.key);
if (cmp < 0)
p = p.left;
else if (cmp > 0)
p = p.right;
else
return p;
}
return null;
}
If there is a Comparator (as in your example), the entry is searched based on this Comparator (this is done by getEntryUsingComparator), that's why it is actually found (then removed) , despite the case difference.
This is interesting, so here are some tests with output:
static void test(String... args) {
Set<String> s =new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
s.addAll(Arrays.asList( "a","b","c"));
s.removeAll(Arrays.asList(args));
System.out.println(s);
}
public static void main(String[] args) {
test("C"); output: [a, b]
test("C", "A"); output: [b]
test("C", "A","B"); output: [a, b, c]
test("B","C","A"); output: [a, b, c]
test("K","C"); output: [a, b]
test("C","K","M"); output: [a, b, c] !!
test("C","K","A"); output: [a, b, c] !!
}
Now without the comparator it works just like a sorted HashSet<String>():
static void test(String... args) {
Set<String> s = new TreeSet<String>();//
s.addAll(Arrays.asList( "a","b","c"));
s.removeAll(Arrays.asList(args));
System.out.println(s);
}
public static void main(String[] args) {
test("c"); output: [a, b]
test("c", "a"); output: [b]
test("c", "a","b"); output: []
test("b","c","a"); output: []
test("k","c"); output: [a, b]
test("c","k","m"); output: [a, b]
test("c","k","m"); output: [a, b]
}
Now from the documentation:
public boolean removeAll(Collection c)
Removes from this set all of its elements that are contained in the
specified collection (optional operation). If the specified collection
is also a set, this operation effectively modifies this set so that
its value is the asymmetric set difference of the two sets.
This implementation determines which is the smaller of this set and
the specified collection, by invoking the size method on each. If this
set has fewer elements, then the implementation iterates over this
set, checking each element returned by the iterator in turn to see if
it is contained in the specified collection. If it is so contained, it
is removed from this set with the iterator's remove method. If the
specified collection has fewer elements, then the implementation
iterates over the specified collection, removing from this set each
element returned by the iterator, using this set's remove method.
Source
Related
I have the following comparator for my TreeSet:
public class Obj {
public int id;
public String value;
public Obj(int id, String value) {
this.id = id;
this.value = value;
}
public String toString() {
return "(" + id + value + ")";
}
}
Obj obja = new Obj(1, "a");
Obj objb = new Obj(1, "b");
Obj objc = new Obj(2, "c");
Obj objd = new Obj(2, "a");
Set<Obj> set = new TreeSet<>((a, b) -> {
System.out.println("Comparing " + a + " and " + b);
int result = a.value.compareTo(b.value);
if (a.id == b.id) {
return 0;
}
return result == 0 ? Integer.compare(a.id, b.id) : result;
});
set.addAll(Arrays.asList(obja, objb, objc, objd));
System.out.println(set);
It prints out [(1a), (2c)], which removed the duplicates.
But when I changed the last Integer.compare to Integer.compare(b.id, a.id) (i.e. switched the positions of a and b), it prints out [(2a), (1a), (2c)]. Clearly the same id 2 appeared twice.
How do you fix the comparator to always remove the duplicates based on ids and sort the ordered set based on value (ascending) then id (descending)?
You're askimg:
How do you fix the comparator to always remove the duplicates based on ids and sort the ordered set based on value (ascending) then id (descending)?
You want the comparator to
remove duplicates based on Obj.id
sort the set by Obj.value and Obj.id
Requirement 1) results in
Function<Obj, Integer> byId = o -> o.id;
Set<Obj> setById = new TreeSet<>(Comparator.comparing(byId));
Requirement 2) results in
Function<Obj, String> byValue = o -> o.value;
Comparator<Obj> sortingComparator = Comparator.comparing(byValue).thenComparing(Comparator.comparing(byId).reversed());
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
Let's have a look on the JavaDoc of TreeSet. It says:
Note that the ordering maintained by a set [...] must be consistent with equals if it is to
correctly implement the Set interface. This is so
because the Set interface is defined in terms of the equals operation,
but a TreeSet instance performs all element comparisons using its
compareTo (or compare) method, so two elements that are deemed equal
by this method are, from the standpoint of the set, equal.
The set will be ordered according to the comparator but its elements are also compared for equality using the comparator.
As far as I can see there is no way to define a Comparator which satisfies both requirements. Since a TreeSet is in the first place a Set requirement 1) has to match. To achieve requirement 2) you can create a second TreeSet:
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
setByValueAndId.addAll(setById);
Or if you don't need the set itself but to process the elements in the desired order you can use a Stream:
Consumer<Obj> consumer = <your consumer>;
setById.stream().sorted(sortingComparator).forEach(consumer);
BTW:
While it's possible to sort the elements of a Stream according to a given Comparator there is no distinct method taking a Comparator to remove duplicates according to it.
EDIT:
You have two different tasks: 1. duplicate removal, 2. sorting. One Comparator cannot solve both tasks. So what alternatives are there?
You can override equals and hashCode on Obj. Then a HashSet or a Stream can be used to remove duplicates.
For the sorting you still need a Comparator (as shown above). Implementing Comparable just for sorting would result in an ordering which is not "consistent with equals" according to Comparable JavaDoc.
Since a Stream can solve both tasks, it would be my choice. First we override hashCode and equals to identify duplicates by id:
public int hashCode() {
return Integer.hashCode(id);
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Obj other = (Obj) obj;
if (id != other.id)
return false;
return true;
}
Now we can use a Stream:
// instantiating one additional Obj and reusing those from the question
Obj obj3a = new Obj(3, "a");
// reusing sortingComparator from the code above
Set<Obj> set = Stream.of(obja, objb, objc, objd, obj3a)
.distinct()
.sorted(sortingComparator)
.collect(Collectors.toCollection(LinkedHashSet::new));
System.out.println(set); // [(3a), (1a), (2c)]
The returned LinkedHashSet has the semantics of a Set but it also preserved the ordering of sortingComparator.
EDIT (answering the questions from comments)
Q: Why it didn't finish the job correctly?
See it for yourself. Change the last line of your Comparator like follows
int r = result == 0 ? Integer.compare(a.id, b.id) : result;
System.out.println(String.format("a: %s / b: %s / result: %s -> %s", a.id, b.id, result, r));
return r;
Run the code once and then switch the operands of Integer.compare. The switch results in a different comparing path. The difference is when (2a) and (1a) are compared.
In the first run (2a) is greater than (1a) so it's compared with the next entry (2c). This results in equality - a duplicate is found.
In the second run (2a) is smaller than (1a). Thus (2a) would be compared as next with a previous entry. But (1a) is already the smallest entry and there is no previous one. Hence no duplicate is found for (2a) and it's added to the set.
Q: You said one comparator can't finish two tasks, my 1st comparators in fact did both tasks correctly.
Yes - but only for the given example. Add Obj obj3a to the set as I did and run your code. The returned sorted set is:
[(1a), (3a), (2c)]
This violates your requirement to sort for equal values descending by id. Now it's ascending by id. Run my code and it returns the right order, as shown above.
Struggling with a Comparator a time ago I got the following comment: "... it’s a great exercise, demonstrating how tricky manual comparator implementations can be ..." (source)
I was checking headMap method of TreeMap which returns a portion of Map whose keys are strictly less than toKey. So I was expecting output to be B, C but it returns only B. Here is a thing I did weird I changed compareTo method like this return this.priority > o.priority ? 1 : -1; then it started returning C, B which is I was expecting. I am sure this is not correct but how can I get both B, C which has lower priority than A. Where I am getting it wrong. Thanks.
NavigableMap<PolicyTypePriorityWrapper, String> treeMap = new TreeMap();
PolicyTypePriorityWrapper a = new PolicyTypePriorityWrapper("A", 2);
PolicyTypePriorityWrapper b = new PolicyTypePriorityWrapper("B", 1);
PolicyTypePriorityWrapper c = new PolicyTypePriorityWrapper("C", 1);
treeMap.put(a, "A");
treeMap.put(b, "B");
treeMap.put(c, "C");
NavigableMap<PolicyTypePriorityWrapper, String> map = treeMap.headMap(a, false);
Set<PolicyTypePriorityWrapper> policyTypePriorityWrappers = map.keySet();
for (PolicyTypePriorityWrapper pol: policyTypePriorityWrappers) {
System.out.println(pol.getPolicyType());
}
PolicyTypePriorityWrapper.java
class PolicyTypePriorityWrapper implements Comparable<PolicyTypePriorityWrapper> {
private String policyType;
private int priority;
public PolicyTypePriorityWrapper(final String policyType, final int priority) {
this.policyType = policyType;
this.priority = priority;
}
public String getPolicyType() {
return this.policyType;
}
public int getPriority() {
return this.priority;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PolicyTypePriorityWrapper that = (PolicyTypePriorityWrapper) o;
if (priority != that.priority) return false;
return policyType.equals(that.policyType);
}
#Override
public int hashCode() {
int result = policyType.hashCode();
result = 31 * result + priority;
return result;
}
#Override
public int compareTo(final PolicyTypePriorityWrapper o) {
return Integer.compare(this.priority, o.priority);
}
}
That's because you are not following JDK documentation guidelines, from Comprarable:
It is strongly recommended (though not required) that natural orderings be consistent with equals. This is so because sorted sets (and sorted maps) without explicit comparators behave "strangely" when they are used with elements (or keys) whose natural ordering is inconsistent with equals. In particular, such a sorted set (or sorted map) violates the general contract for set (or map), which is defined in terms of the equals method.
As you can see you have circumstances in which a.compareTo(b) == 0 but !a.equals(b). Both "B", 1 and "C", 1 are considered equal for the TreeMap:
Note that the ordering maintained by a tree map, like any sorted map, and whether or not an explicit comparator is provided, must be consistent with equals if this sorted map is to correctly implement the Map interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Map interface is defined in terms of the equals operation, but a sorted map performs all key comparisons using its compareTo (or compare) method, so two keys that are deemed equal by this method are, from the standpoint of the sorted map, equal. The behavior of a sorted map is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Map interface.
For example, if one adds two keys a and b such that (!a.equals(b) && a.compareTo(b) == 0) to a sorted set that does not use an explicit comparator, the second add operation returns false (and the size of the sorted set does not increase) because a and b are equivalent from the sorted set's perspective.
So what happens is that you compareTo is not able to distinguish two elements with same priority but different type, but since a TreeMap is using ONLY that method to decide if two elments are equal then you are not adding them both to the map in the first place.
Did you try if treeMap.size() == 3? My guess is that it's 2 in the first place.
The new PolicyTypePriorityWrapper("B", 1) is not qualified because it does it even not make it into the treeMap.
Why? Because the keys are the PolicyTypePriorityWrapper objects which are compared according to their integer priority value. Since b and c have the same priority, only the last one is saved to the treeMap. Compared a, b and c has a lower priority than a and equal to b. The key remains and the value is replaced. So in the map appears an entry PolicyTypePriorityWrapper b with the newly replaced value C.
It's the behavior of Map::put(K key, V value) method.
If the map previously contained a mapping for the key, the old value is replaced by the specified value.
Now the NavigableMap::headMap(K toKey, boolean inclusive) which returns a view of the portion of this map whose keys are less than (or equal to, if inclusive is true) toKey (taken from the documentation). The result is obvious. Only a and b stay in the treeMap, so the a is filtered out since it has smaller priority to b and only b is qualified to be returned.
To be specific, I have two lists:
List<SystemUserWithNameAndId> list1;
List<SystemUserWithNameAndId> list2;
I want to check if they contain the same system users and ordering is not an issue. I tried to use a comparator to sort them first and then check if they're equal using the equals() method of lists. But I don't want to override the equals method for SystemUserWithNameAndId and I was wondering if I could use the comparator I created for sorting or a similar one to check for equality without explicitly iterating through the lists after sorting.
Comparator<SystemUserWithNameAndId> systemUserComparator = new Comparator<SystemUserWithNameAndId>()
{
#Override
public int compare(SystemUserWithNameAndId systemUser1, SystemUserWithNameAndId systemUser2)
{
final int systemUserId1 = systemUser1.getSystemUserId();
final int systemUserId2 = systemUser2.getSystemUserId();
return systemUserId1 == systemUserId2
? 0
: systemUserId1 - systemUserId2;
}
};
Collections.sort(systemUsers1, systemUserComparator);
Collections.sort(systemUsers2, systemUserComparator);
return systemUsers1.equals(systemUsers2);
Ideally, I want to be able to say,
CollectionUtils.isEqualCollections(systemUsers1, systemUsers2, someCustomComparator);
Just implement the method that iterates, and reuse it every time you need it:
public static <T> boolean areEqualIgnoringOrder(List<T> list1, List<T> list2, Comparator<? super T> comparator) {
// if not the same size, lists are not equal
if (list1.size() != list2.size()) {
return false;
}
// create sorted copies to avoid modifying the original lists
List<T> copy1 = new ArrayList<>(list1);
List<T> copy2 = new ArrayList<>(list2);
Collections.sort(copy1, comparator);
Collections.sort(copy2, comparator);
// iterate through the elements and compare them one by one using
// the provided comparator.
Iterator<T> it1 = copy1.iterator();
Iterator<T> it2 = copy2.iterator();
while (it1.hasNext()) {
T t1 = it1.next();
T t2 = it2.next();
if (comparator.compare(t1, t2) != 0) {
// as soon as a difference is found, stop looping
return false;
}
}
return true;
}
Here's a Java 8 way of solving your problem. First make sure the lists are of equal length:
List<SystemUserWithNameAndId> list1 = ... ;
List<SystemUserWithNameAndId> list2 = ... ;
if (list1.size() != list2.size()) {
return false;
}
Now build a Comparator using the new comparator utilities. The idea is that instead of writing custom logic for a comparator, most comparators do something like comparing two objects by extracting a key from them, and then comparing the keys. That's what this does.
Comparator<SystemUserWithNameAndId> comp =
Comparator.comparingInt(SystemUserWithNameAndId::getSystemUserId);
Sort the lists. Of course, you might want to make copies before sorting if you don't want your function to have the side effect of sorting its input. If your input lists aren't random access (who uses LinkedList nowadays?) you might also want to copy them to ArrayLists to facilitate random access.
list1.sort(comp);
list2.sort(comp);
Run a stream over the indexes of the lists, calling the comparator on each pair. The comparator returns 0 if the elements are equals according to this comparator. If this is true for all pairs of elements, the lists are equal.
return IntStream.range(0, list1.size())
.allMatch(i -> comp.compare(list1.get(i), list2.get(i)) == 0);
I'm looking for some kind of set data structure that can meet both of these requirements:
Sorted
O(1) for lookup
This is what I got so far, but I really hope there's an existing, less-awkward, data structure out there.
/**
* This MUST support both
* (1) Looking up by A - O(n)
* (2) Iteration by sorted Foo<A, B>
*/
public class MySet<Foo<A, B>> extends TreeSet<Foo<A, B>>
{
private Map<A, Foo<A, B>> temp = new HashMap<A, Foo<A, B>>();
public Foo<A, B> getNode(A a)
{
return temp.get(a);
}
#Override
public boolean add(Foo<A, B> foo)
{
temp.put(foo.getA(), foo);
return super.add(foo);
}
}
And my Foo class looks like this:
public class Foo<A, B>
{
private A a; //Can NEVER be null
private B b; //Can NEVER be null
//... constructor and stuff omitted
public int compareTo(Foo<A, B> that)
{
if (this.equals(that))
return 0;
//Compare by a first
int ret = this.a.compareTo(that);
if (ret == 0)
return 0;
//Compare by b
return this.b.compareTo(that.b);
}
public boolean equals(Object obj)
{
if (!(obj instanceof Foo))
return false;
Foo rhs = (Foo) obj;
return this.a.equals(rhs.a) && this.b.equals(rhs.b);
}
}
UPDATE:
Here's a use case for my set:
MySet<Foo<SomeA, SomeB>> mySet = getTheData(); //getTheData() returns a set with a bunch of Foo objects
SomeA a = getA(); //getA() returns some instance of SomeA that I'm interested in
I want to be able to check the set and RETRIEVE a Foo object (if exists) such that Foo.getA() == a;
mySet.getNode(a);
You can get it by using some additional space. So you need a HashSet. Additionally, each element will point to the next value in the sort order. Let's say you have keys 1, 3, 5, 10 and you are using linear probing.
value array = [3, 5, null, null, 10, 1];
pointer array = [1, 4, null, null, null, 0];
So the value array contains the values. The hash function decides where the value goes. so in the above example, h(1) = 5 (1 goes to index 5), h(3) = 0, h(5) = 1, and h(10) = 4. The indexes 2, 3 have null (open spaces for future elements). The pointer array says which element follows the current element in the sorting order. So let's say we are doing set.contains(3), it will result in computing h(3) (which will yield 0), and we know that the element exists in the set. If we want the next element in the set of elements according to sort order, we look at the value in the pointer array. So for value 3 (which is at position 0 in the value array), we get the next element in the sort order by looking up the index in the pointer array (pointer_array[0], which is 1), and then looking up value_array[1], which is 5.
This is a very common implementation. Java's LinkedHashMap is usually used as a LRU cache, which is implemented as a hash map + a doubly linked list of keys. The keys in the doubly linked list are in the order of their access.
In your case, when you insert an element, you need to adjust your pointer array which is very slow. You have to do a linear scan. If this is not read only, you can use the following approach.
In your data structure, have a hashset and a avl tree, a red black tree or any other balanced binary tree. Whenever you do a containsKey test, it's O(1). Whenever you are enumerating, you can traverse them using the binary tree in sorted order in linear time. Whenever you are inserting a new element, you also insert it into both the binary tree and HashSet. When you delete, you delete the element from the hash set and the binary tree. So deletes and inserts become O(log n).
I think you should try using MultiMaps in google guava library.
Its pretty simple to use also:
Map<Salesperson, List<Sale>> map = new Hashmap<SalesPerson, List<Sale>>();
public void makeSale(Salesperson salesPerson, Sale sale) {
List<Sale> sales = map.get(salesPerson);
if (sales == null) {
sales = new ArrayList<Sale>();
map.put(salesPerson, sales);
}
sales.add(sale);
}
can be replaced by,
Multimap<Salesperson, Sale> multimap = new ArrayListMultimap<Salesperson,Sale>();
public void makeSale(Salesperson salesPerson, Sale sale) {
multimap.put(salesperson, sale);
}
But you have to be careful here, multimaps will preserve the entries with same keys unlike hashmaps which replaces the equivalent keys with the latest one.
Google Guava Libraries feature a lot of other data structures with different functionality. You can find the information about it on its wiki.
Hope this was helpful.
I need to check if any of the values in one arraylist is present in another arraylist:
import java.util.ArrayList;
public class SampleCode {
ArrayList<Integer> in = new ArrayList<>();
ArrayList<Integer> is = new ArrayList<>();
public static void main(String[] args) {
new SampleCode().work();
}
public void work(){
in.add(3);in.add(4);in.add(5);
is.add(1);is.add(2);is.add(3);
if(is.containsAll(in)){
System.out.println("It does not contain");
}
}
}
It prints "It does not contain". I need to know if there is a way to compare these two arraylists and if any of the values are present in the other arraylist, it should return false. I know iterating can help. Is there any simple way to do this?
I think you can use
Collections.disjoint
which says
Returns true if the two specified collections have no elements in common.
so it will return false if there are any elements in common.
Another possible solution:
public static boolean containsNone(List<?> list, List<?> of) {
List<?> temp = new ArrayList<Object>(list);
temp.retainAll(of);
return temp.isEmpty();
}
For example:
List<String> ref = Arrays.asList("w1", "w2", "w3");
List<String> ok = Arrays.asList("w4", "w5");
List<String> ko = Arrays.asList("w1", "w5");
System.out.println(containsNone(ok, ref));
System.out.println(containsNone(ko, ref));
Prints:
true
false
Try this one
public void work(){
in.add(3);in.add(4);in.add(5);;
is.add(1);is.add(2);is.add(3);;
ArrayList<Integer> matched = new ArrayList<Integer>(in);
matched.retainAll(is);
if(matched.size()>0){
System.out.println(matched);
}else{
System.out.println("It does not contain");
}
}
Collection.indexOfSubList(List<?> source, List<?> target)
Returns the starting position of the first occurrence of the specified
target list within the specified source list, or -1 if there is no
such occurrence.
More formally, returns the lowest index i such that source.subList(i, i+target.size()).equals(target), or -1 if there is no such index. (Returns -1 if target.size() > source.size().)
This implementation uses the "brute force" technique of scanning over the source list, looking for a match with the target at each location in turn.
Collections.disjoint(Collection<?> c1, Collection<?> c2)
Returns true if the two specified collections have no elements in
common.
Care must be exercised if this method is used on collections that do not comply with the general contract for Collection. Implementations may elect to iterate over either collection and test for containment in the other collection (or to perform any equivalent computation). If either collection uses a nonstandard equality test (as does a SortedSet whose ordering is not compatible with equals, or the key set of an IdentityHashMap), both collections must use the same nonstandard equality test, or the result of this method is undefined.
Care must also be exercised when using collections that have restrictions on the elements that they may contain. Collection implementations are allowed to throw exceptions for any operation involving elements they deem ineligible. For absolute safety the specified collections should contain only elements which are eligible elements for both collections.
Note that it is permissible to pass the same collection in both parameters, in which case the method will return true if and only if the collection is empty.
Throws:
NullPointerException - if one collection contains a null element and null is not an eligible element for the other collection. (optional) NullPointerException - if one collection contains a null element and null is not an eligible element for the other collection. (optional) ClassCastException - if one collection contains an element that is of a type which is ineligible for the other collection. (optional)
Collections.disjoint(list1, list2);
is your answer
see Collections documentation
public boolean isListNotOverlapping(List<Integer> yourList1, List<Integer> yourList2) {
for(Integer i : yourList1) {
if (yourList2.contains(i)) {
return false;
}
}
return true;
}