java TreeSet: comparing and equality - java

I'd like to have list of object sorted with property 'sort_1'. But when I want to remove I'd like it to use property 'id'. The following code represents the problem.
package javaapplication1;
import java.util.TreeSet;
public class MyObj implements Comparable<MyObj> {
public long sort_1;
public long id;
public MyObj(long sort, long id) {
this.sort_1=sort;
this.id=id;
}
#Override
public int compareTo(MyObj other) {
int ret = Long.compare(sort_1, other.sort_1);
return ret;
}
public String toString() {
return id+":"+sort_1;
}
public static void main(String[] args) {
TreeSet<MyObj> lst=new TreeSet<MyObj>();
MyObj o1 = new MyObj(99,1);
MyObj o2 = new MyObj(11,9);
lst.add(o1);
lst.add(o2);
System.out.println(lst);
MyObj o3 = new MyObj(1234, 1);
//remove myObje with id 1
boolean remove=lst.remove(o3);
System.out.println(lst);
}
}
Output of this code is:
[9:11, 1:99]
[9:11, 1:99]
I need to have list sorted as I do a lot of additions to the list. I don't want to explicitly use any 'sort' method. What are my options ?
EDIT:
My requirement is to have: objects with 'id' as unique but there can be object's with duplicate 'sort' value.

Just by chance I found this out yesterday as well. This seems to be an artifact of the implementation of TreeMap (which is what TreeSet uses to store its entries).
TreeMap uses a binary search tree for storing the key/value pairs, but it only ever uses the given Comparator (or the compare function if the key class implements Comparable) to check for equality, as you can see in this code exxcerpt:
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;
}
I'd almost call this a (not really fixable) bug since the JavaDoc of the Comparable interface explicitly says that returning 0 with the compareTo function does not have to imply "equalness":
It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y)).
You won't be able to store stuff in the TreeSet the way you want it to. I'd recommend using a normal HashMap or a LinkedHashMap and then just sorting the output when you need to sort it with Collections.sort.
Besides all of this, I always find it strange to implement the Comparable interface. Most things don't really have a "natural" ordering that is immediately obvious. Sometimes this can lead to strange bugs (like this one!), so I typically always sort only when I need it using custom Comparators. Java 8 makes writing those really easy as well!

I think the problem you're having is that you are implementing Comparable, but your implementation seems to be inconsistent with equals - and you have not implemented any equality methods. That is:
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
In your case, when you build these three objects:
MyObj o1 = new MyObj(99,1);
MyObj o2 = new MyObj(11,9);
MyObj o3 = new MyObj(1234, 1);
You will see that o1.compareTo(o3) == -1, while o1.equals(o3) == false.
But you seem to want o1.equals(o3) == true.
Also, recognize that TreeSet.add() returns false if the object already exists in the set. This check is based on the equals() method.
To remedy this, override Object.equals() and Object.hashCode() such that they take into consideration the MyObj.id field, and continue to use the sort_1 field in the compareTo() method when they are not equal.
package javaapplication1;
import java.util.TreeSet;
public class MyObj implements Comparable<MyObj> {
public long sort_1;
public long id;
public MyObj(long sort, long id) {
this.sort_1 = sort;
this.id = id;
}
#Override
public int compareTo(MyObj other) {
return (this.equals(other))? 0 : Long.compare(sort_1, other.sort_1);
}
#Override
public boolean equals(Object obj) {
MyObj other = (MyObj) obj;
return this.id == other.id && this.sort_1 == other.sort_1;
}
#Override
public int hashCode() {
return (int) id;
}
public String toString() {
return id + ":" + sort_1;
}
public static void main(String[] args) {
TreeSet<MyObj> lst = new TreeSet<MyObj>();
MyObj o1 = new MyObj(99L, 1L);
MyObj o2 = new MyObj(11L, 9L);
MyObj o3 = new MyObj(1234L, 1L);
MyObj o4 = new MyObj(1234L, 1L);
System.out.println( "Adding o1: " + lst.add(o1));
System.out.println( "Adding o2: " + lst.add(o2));
System.out.println( "Adding o3: " + lst.add(o3));
System.out.println( "Adding o4: " + lst.add(o4));
System.out.println(lst);
System.out.println("o1.compareTo(o3) : " + o1.compareTo(o3));
System.out.println("o1.equals(o3) : " + o1.equals(o3));
//remove myObje with id 1
boolean remove = lst.remove(o3);
System.out.println(lst);
}
}
Output:
Adding o1: true
Adding o2: true
Adding o3: true
Adding o4: false
[9:11, 1:99, 1:1234]
o1.compareTo(o3) : -1
o1.equals(o3) : false
[9:11, 1:99]

Use Map<Long,MyObject> objectsByIDs; to store your data objects by id: objectsByIDs.put(id,myObjectInstance);. Then you may retrieve them from the map this wayMyObject o = objectsByIDs.get(id); And remove it from both: objectsByIDs.remove(o); lst.remove(o).

this is odd indeed. The documentation of TreeSet.remove() explicitly states that the method invokes equals() in order to find the argument in the Set.
However, the stack trace for remove looks like this
Thread [main] (Suspended (breakpoint at line 18 in MyObj))
MyObj.compareTo(MyObj) line: 18
MyObj.compareTo(Object) line: 1
TreeMap<K,V>.getEntry(Object) line: not available
TreeMap<K,V>.remove(Object) line: not available
TreeSet<E>.remove(Object) line: not available
MyObj.main(String[]) line: 45
Even using Comparator does not work. Seems to me like some smart developer at Sun/Oracle/openJDK thought that doing compareTo() == 0 is the same as equals(). it is not.
You're only option is either use an external data structure to check equality as was suggested, or do the loop yourself, find the item you want, and remove it.
EDIT:
Now I get it. they search for the item using binary search, that is why they do compareTo().

Having a different logic for remove and sorting in TreeSet is almost certainly impossible, and even if it was possible it would break if you looked at it funny. Don't do that.
Trying to mess with the comparator so it does something magic is a terrible idea. Accept that there is one and only one notion of comparison the TreeSet will care about. Anything you want to do with another notion of comparison shouldn't use the TreeSet methods to do that.
What you can do instead is have a special removeId(int) method that does something like
void removeId(int id) {
Iterator<MyObj> itr = set.iterator();
while (itr.hasNext()) {
if (itr.next().id == id) {
itr.remove();
break;
}
}
}

Related

How to sort sortedset by value that can be duplicate?

In Java 1.7, I have a "Post class" that has the Post ID and the number of votes of every Post. I want to create sorted set of Posts that can be always sorted by the number of votes. Please be informed that different Posts can have the same number of votes.
The problem is that when I create 2 different Posts with 2 different IDs and different number of votes, the sorted set detects that they are different Posts and thus add them twice instead of replacing the existing thread with the number of new votes. The example below
Post Class:
public class Post implements Comparable<Post> {
protected int id;
protected int votes;
public Post(int id) {
this.id = id;
this.votes = 0;
}
public Post(int id, int votes) {
this.id = id;
this.votes = votes;
}
#Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) {
return false;
}
Post post= (Post) o;
return id == employee.id;
}
#Override
public int hashCode() {
return Objects.hash(this.id);
}
#Override
public int compareTo(Post t) {
int diff = ((Integer) t.votes).compareTo(this.votes);
if (diff == 0) {
return ((Integer) t.id).compareTo(this.id);
}
return diff;
}
}
Run Method:
public void run() {
SortedSet<Post> set = new TreeSet<Post>();
Post t1 = new Post(1, 30);
Post t2 = new Post(1, 40);
Post t3 = new Post(2, 100);
set.add(t1);
set.add(t2);
set.add(t3);
for (Post t : set) {
System.err.println(t.id + " >> " + t.votes);
}
}
Expected Output:
2 >> 100
1 >> 40
Actual Output
2 >> 100
1 >> 40
1 >> 30
As you can see the problem is that the same Post appeared twice in the set which is not the desired output.
I also tried to avoid using Comparable interface and instead I used Comparator, yet, I got the same result.
Comparator Class:
class CompareByVotes implements Comparator<Post> {
#Override
public int compare(Post t1, Post t2) {
int diff = ((Integer) t2.votes).compareTo(t1.votes);
if (diff == 0) {
return ((Integer) t2.id).compareTo(t1.id);
}
return diff;
}
}
Question:
Any changes required to get it work as desired ?
Your compareTo() method doesn't return 0 when the objects you compare are equal based on the equals() method. However, this is required by the SortedSet interface:
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.
So your compareTo() method must return 0 when they are equal. One possible solution would be something like this:
public int compareTo(Post t) {
if (equals(t)) {
return 0;
}
int diff = ((Integer) t.votes).compareTo(this.votes);
if (diff == 0) {
return ((Integer) t.id).compareTo(this.id);
}
return diff;
}
Also, keep in mind that add() does not "overwrite" the object, when an equal object is already in the set. See the documentation of add():
[...] If this set already contains the element, the call leaves the set unchanged and returns false.

Object as a key in treemap in java 8

CompareObj is a class in java It consists of three attributes String rowKey, Integer hitCount, Long recency
public CompareObj(String string, Integer i) {
this.rowKey = string;
this.hitCount = i%10;
this.recency= (Long) i*1000;
}
Now I created a treeMap
Comparator<CompareObj> comp1 = (e1,e2) -> e1.getHitCount().compareTo(e2.getHitCount());
Comparator<CompareObj> comp2 = (e1,e2) -> e2.getRecency().compareTo(e1.getRecency());
Comparator<CompareObj> result = comp1.thenComparing(comp2);
TreeMap<CompareObj, CompareObj> tM = new TreeMap<CompareObj, CompareObj>(result);
for(int i=0;i<=1000;i++)
{
CompareObj cO = new CompareObj("A"+i, i);
tM.put(cO,cO);
}
for(int i=0;i<=1000;i++)
{
CompareObj cO = new CompareObj("A"+i, i);
CompareObj values = tM.get(cO);
System.out.println(values.getRowKey()); // Line 28: get Null Pointer Exception
}
Also I overide hashCode and Equals. Still I get nullponter exception.
#Override
public int hashCode() {
return Objects.hash(getRowKey());
}
#Override
public boolean equals(Object obj) {
if(this==obj) return true;
if(!(obj instanceof CompareObj)) return false;
CompareObj compareObj = (CompareObj) obj;
return Objects.equals(this.getRowKey(), compareObj.getRowKey());
}
Here when I try to retrive value from treemap back I get Null Pointer exception in the line mentioned. How to solve this
If I want to implement comapareTo() of Comaprable interface, how should I implement if there is multiple sort conditions.
The first thing to understand, is the NullPointerException. If you get that exception on the exact line
System.out.println(values.getRowKey());
then either System.out or values is null. Since we can preclude System.out being null, it’s the values variable, which contains the result of get and can be null if the lookup failed.
Since you are initializing the TreeMap with a custom Comparator, that Comparatordetermines equality. Your Comparator is based on the properties getHitCount() and getRecency() which must match, which implies that when the lookup fails, the map doesn’t contain an object having the same values as reported by these two methods.
You show that you construct objects with the same values but not the code of these getters. There must be an inconsistency. As Misha pointed out, your posted code can’t be the code you have ran when getting the exception, therefore we can’t help you further (unless you post the real code you ran).

getting an object from an arrayList with objects attribute

I have 2 classes.
public class klass1 {
String bir;
String myID;
klass1(String bir, String myID)
{
this.bir=bir;
this.myID=myID;
}
}
.
import java.util.*;
public class dd {
public static void main(String[] args) {
ArrayList<Object> ar=new ArrayList();
ar.add(new klass1("wer","32"));
ar.add(new klass1("das","23"));
ar.add(new klass1("vz","45"));
ar.add(new klass1("yte","12"));
ar.add(new klass1("rwwer","43"));
ar.remove(new klass1("vz","45"));//it's not worked!!!
System.out.println(ar.size());
}
}
What I want is removing or getting an object from array list with object's second attribute. How can I do that? Is there an easy way for it?
Just implement the equals method in the class Klass1.
public class Klass1 {
String bir;
String myID;
Klass1(String bir, String myID)
{
this.bir=bir;
this.myID=myID;
}
public boolean equals(Object o){
if(o instanceof Klass1)
return ((Klass1)o).myID.equals(myID);
else
return false;
}
}
Its because you are trying to delete a new object which isnt in the arraylist. When you use new klass1("vz","45") you are creating a new instance of this class which isnt in the arraylist.
What the system does internally is to compare those classes using equals. Why this doesn't work is explained in the following code:
Object o1 = new Object();
Object o2 = new Object();
System.out.println(o1 == o2); // false, obviously
System.out.println(o1.equals(o2)); // false
System.out.println(o1); // java.lang.Object#17046822
System.out.println(o2); // java.lang.Object#22509bfc
You can tell by the number following the # that these objects have a different hash values, and this is what the equals function of Object does check.
This is relevant for your klass, because unless you overwrite equals, you will use the equals of Object. And if you implement equals you should always implement hashcode as well. Because both tell you something about whether or not two objects are the "same", and if the one says something else than the other, some part of your code might get confused.
How to properly implement equals for your class:
#Override
public int hashCode() {
int hash = 7;
hash = 17 * hash + Objects.hashCode(this.bir);
hash = 17 * hash + Objects.hashCode(this.myID);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final klass1 other = (klass1) obj;
if (!Objects.equals(this.bir, other.bir)) {
return false;
}
if (!Objects.equals(this.myID, other.myID)) {
return false;
}
return true;
}
This can be done in most IDEs btw with a shortcut (i.E. alt-insert in Netbeans). Note that I did this in Java 7 using Objects. If you are in Java 6, you need to manually type(a == b) || (a != null && a.equals(b)); with the appropriate objects to compare.
Creating a proper hashcode is not always trivial, for more complex objects you might want to read a bit about hashcodes first. For simple objects: multiply primes with something.
The equals method is usually trivial, it is just important to first check for null and for class equality. This is often forgotten by programmers and a common source for NullPointerExceptions and ClassCastExceptions.

Java: Retrieving an element from a HashSet

Why cannot I retrieve an element from a HashSet?
Consider my HashSet containing a list of MyHashObjects with their hashCode() and equals() methods overridden correctly. I was hoping to construct a MyHashObject myself, and set the relevant hash code properties to certain values.
I can query the HashSet to see if there "equivalent" objects in the set using the contains() method. So even though contains() returns true for the two objects, they may not be == true.
How come then there isn’t any get() method similar to how the contains() works?
What is the thinking behind this API decision?
If you know what element you want to retrieve, then you already have the element. The only question for a Set to answer, given an element, is whether it contains() it or not.
If you want to iterator over the elements, just use a Set.iterator().
It sounds like what you're trying to do is designate a canonical element for an equivalence class of elements. You can use a Map<MyObject,MyObject> to do this. See this Stack Overflow question or this one for a discussion.
If you are really determined to find an element that .equals() your original element with the constraint that you must use the HashSet, I think you're stuck with iterating over it and checking equals() yourself. The API doesn't let you grab something by its hash code. So you could do:
MyObject findIfPresent(MyObject source, HashSet<MyObject> set)
{
if (set.contains(source)) {
for (MyObject obj : set) {
if (obj.equals(source))
return obj;
}
}
return null;
}
It is brute-force and O(n) ugly, but if that's what you need to do...
You can use HashMap<MyHashObject, MyHashObject> instead of HashSet<MyHashObject>.
Calling containsKey() on your "reconstructed" MyHashObject will first hashCode() - check the collection, and if a duplicate hashcode is hit, finally equals() - check your "reconstructed" against the original, at which you can retrieve the original using get()
Complexity is O(1) but the downside is you will likely have to override both equals() and hashCode() methods.
It sounds like you're essentially trying to use the hash code as a key in a map (which is what HashSets do behind the scenes). You could just do it explicitly, by declaring HashMap<Integer, MyHashObject>.
There is no get for HashSets because typically the object you would supply to the get method as a parameter is the same object you would get back.
If you know the order of elements in your Set, you can retrieve them by converting the Set to an Array. Something like this:
Set mySet = MyStorageObject.getMyStringSet();
Object[] myArr = mySet.toArray();
String value1 = myArr[0].toString();
String value2 = myArr[1].toString();
The idea that you need to get the reference to the object that is contained inside a Set object is common. It can be archived by 2 ways:
Use HashSet as you wanted, then:
public Object getObjectReference(HashSet<Xobject> set, Xobject obj) {
if (set.contains(obj)) {
for (Xobject o : set) {
if (obj.equals(o))
return o;
}
}
return null;
}
For this approach to work, you need to override both hashCode() and equals(Object o) methods
In the worst scenario we have O(n)
Second approach is to use TreeSet
public Object getObjectReference(TreeSet<Xobject> set, Xobject obj) {
if (set.contains(obj)) {
return set.floor(obj);
}
return null;
}
This approach gives O(log(n)), more efficient.
You don't need to override hashCode for this approach but you have to implement Comparable interface. ( define function compareTo(Object o)).
One of the easiest ways is to convert to Array:
for(int i = 0; i < set.size(); i++) {
System.out.println(set.toArray()[i]);
}
If I know for sure in my application that the object is not used in search in any of the list or hash data structure and not used equals method elsewhere except the one used indirectly in hash data structure while adding. Is it advisable to update the existing object in set in equals method. Refer the below code. If I add the this bean to HashSet, I can do group aggregation on the matching object on key (id). By this way I am able to achieve aggregation functions such as sum, max, min, ... as well. If not advisable, please feel free to share me your thoughts.
public class MyBean {
String id,
name;
double amountSpent;
#Override
public int hashCode() {
return id.hashCode();
}
#Override
public boolean equals(Object obj) {
if(obj!=null && obj instanceof MyBean ) {
MyBean tmpObj = (MyBean) obj;
if(tmpObj.id!=null && tmpObj.id.equals(this.id)) {
tmpObj.amountSpent += this.amountSpent;
return true;
}
}
return false;
}
}
First of all, convert your set to an array. Then, get the item by indexing the array.
Set uniqueItem = new HashSet();
uniqueItem.add("0");
uniqueItem.add("1");
uniqueItem.add("0");
Object[] arrayItem = uniqueItem.toArray();
for(int i = 0; i < uniqueItem.size(); i++) {
System.out.println("Item " + i + " " + arrayItem[i].toString());
}
If you could use List as a data structure to store your data, instead of using Map to store the result in the value of the Map, you can use following snippet and store the result in the same object.
Here is a Node class:
private class Node {
public int row, col, distance;
public Node(int row, int col, int distance) {
this.row = row;
this.col = col;
this.distance = distance;
}
public boolean equals(Object o) {
return (o instanceof Node &&
row == ((Node) o).row &&
col == ((Node) o).col);
}
}
If you store your result in distance variable and the items in the list are checked based on their coordinates, you can use the following to change the distance to a new one with the help of lastIndexOf method as long as you only need to store one element for each data:
List<Node> nodeList;
nodeList = new ArrayList<>(Arrays.asList(new Node(1, 2, 1), new Node(3, 4, 5)));
Node tempNode = new Node(1, 2, 10);
if(nodeList.contains(tempNode))
nodeList.get(nodeList.lastIndexOf(tempNode)).distance += tempNode.distance;
It is basically reimplementing Set whose items can be accessed and changed.
If you want to have a reference to the real object using the same performance as HashSet, I think the best way is to use HashMap.
Example (in Kotlin, but similar in Java) of finding an object, changing some field in it if it exists, or adding it in case it doesn't exist:
val map = HashMap<DbData, DbData>()
val dbData = map[objectToFind]
if(dbData!=null){
++dbData.someIntField
}
else {
map[dbData] = dbData
}

Duplicates in Arraylist, comparing various fields java

I have a code to return an arrayList with the duplicates of an ArrayList
but seems it's not working, I am comparing all items in the array...
public ArrayList<ObjectList> duplicates(ArrayList<ObjectList> someObjectsList) {
ArrayList<ObjectList> ret = new ArrayList<ObjectList>();
for ( ObjectList aSomeObjectsList: someObjectsList) {
String field1 = aSomeObjectsList.get1();
String field2 = aSomeObjectsList.get2();
String field3 = aSomeObjectsList.get3();
String field4 = aSomeObjectsList.get4();
for (ObjectList someObject : ret) {
if (
field1.trim().equals(someObject.get1())&&
field2.trim().equals(someObject.get2())&&
field3.trim().equals(someObject.get3())&&
field4.trim().equals(someObject.get4())
){
ret.add(aSomeObjectsList);
}
}
}
return ret;
}
But i guess I am doing something wrong because it doesn't return anything, and I know it has duplictates under this 4 field criteria
Thanks in advance
for (Object someObject : ret) {
if (
field1.trim().equals(someObject.get1())&&
field2.trim().equals(someObject.get2())&&
field3.trim().equals(someObject.get3())&&
field4.trim().equals(someObject.get4())
){
ret.add(aSomeObjectsList);
}
}
The above loop wouldn't work, since it has the size of zero.
Here you go,
public Set<ObjectList> duplicates(ArrayList<ObjectList> someObjectsList) {
Set<ObjectList> originals = new HashSet<ObjectList>();
Set<ObjectList> duplicates = new HashSet<ObjectList>();
for ( ObjectList aSomeObjectsList: someObjectsList) {
boolean added = originals.add(aSomeObjectsList);
if(!added){
duplicates.add(aSomeObjectsList);
}
}
return duplicates;
}
This would work, provided your ObjectList class have the correct implementation of hashCode() and equals() methods.
Disclaimer: This implementation will not provide the information about how many times a particular object was duplicated in the provided list. It will just tell you that a particular object was duplicated. I assumed that that was your real intention. If you wanna count, how many times, you have to modify the code accordingly.
Hint/Suggestion: You should override the equals() method and place your field equality check in there instead, once and for all.
This shouldn't compile - if aSomeObjectsList is an Object then it doesn't have methods get1(), get2(), etc.
Your logic won't work because you aren't checking each element in your input List against the other elements in the input List; rather, you're trying to check the return List.
Also, this is not a really efficient way to check for duplicates in a collection. A better way would be to use a HashMap, where you could check set membership in roughly constant time. If you have to use a List, then sort it first (assuming your objects have a natural ordering) and check adjacent members for equality.
Barring those two, just use List.contains().
Here's a way you can do this. I have defined a basic class ObjectList that shows a way to implement equals and hashCode. Note that this assumes that all the internal variables are non-null. If these variables can contain null then you will need to check for that when computing the equals/hashCode. Also, the objects in this class must also themselves properly implement equals/hashCode.
public class ObjectList {
private int h;
private Object obj1;
private Object obj2;
private Object obj3;
private Object obj4;
#Override
public boolean equals(final Object o) {
if (!(o instanceof ObjectList))
return false;
final ObjectList that = (ObjectList) o;
return that.obj1.equals(obj1) && that.obj2.equals(obj2)
&& that.obj3.equals(obj3) && that.obj4.equals(obj4);
}
#Override
public int hashCode() {
// caches the hashcode since it could be costly to recompute every time
// but this assumes that your object is essentially immutable
// (which it should be if you are using equals/hashCode. If this is not
// true and you want to just temporarily use this when doing the duplicate
// test, move the h variable definition from the object level to this method
// and remove this if statement.
if (h != 0)
return h;
h = obj1.hashCode();
h = h * 31 + obj2.hashCode();
h = h * 31 + obj3.hashCode();
h = h * 31 + obj4.hashCode();
return h;
}
}
public Collection<ObjectList> duplicates(
final Collection<ObjectList> someObjectsList) {
final Set<ObjectList> unique = new HashSet<ObjectList>(someObjectsList);
final ArrayList<ObjectList> ret = new ArrayList<ObjectList>(someObjectsList);
for (final ObjectList o : unique) {
ret.remove(o);
}
// The ret list now contains the duplicate instances; instances
// with more than two occurrences will occur multiple times still in
// this list.
return ret;
// If you want a list of unique duplicate instances then, comment out the above
// return and uncomment this one.
// return new HashSet<ObjectList>(ret);
}
Using Collection<ObjectList> is better, if you can do that, for both the parameter and returned value so you can vary the implementations (ArrayList, Set, etc).

Categories