To illustrate Kayaman's answer, you could do something like :
public class EqualsWrapper {
private final Object delegate;
public EqualsWrapper(Object toWrap) {
delegate = toWrap;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((delegate == null) ? 0 : delegate.toString().hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
EqualsWrapper other = (EqualsWrapper) obj;
return other.toString().equals(obj.toString());
}
}
public static boolean areListsEqual(List list1, List list2){
Set<EqualsWrapper> l_set1 = list1.stream().map(e -> new EqualsWrapper(e)).collect(Collectors.toSet());
Set<EqualsWrapper> l_set2 = list2.stream().map(e -> new EqualsWrapper(e)).collect(Collectors.toSet());
return l_set1.equals(l_set2);
}
However copying the whole lists might not be something optimal if you have very big lists and a high chance they are not equal.
You could also follow that stance :
public static boolean areListsEqual(List list1, List list2){
return list1.stream().map(e -> new EqualsWrapper(e)).allMatch(e -> list2.stream().map(e -> new EqualsWrapper(e)).anyMatch(e2 -> e2.equals(e)));
}
Where you'll break faster if there is not a match but risk to lose information on potential duplicates.