java - How to find matching objects between two lists?
Given two Lists, each list holding the same object type, I would like t开发者_如何转开发o find objects between the two lists that match, based on some property values.
e.g. an object from List1, L1Obj, matches an object from List2, L2Obj, if L1Obj.a == L2Obj.a AND L1Obj.b == L2Obj.c AND L1Obj.c == L2Obj.c
These properties are not the only properties of the of the class, but are all that is needed to uniquely identify an object within a list.
My question is - what is the best way to achieve this?
One way would be to construct to HashMaps based on the lists, with the concataned String value of a+b+c used as the key to index an object. That way I could iterate through the first list, and attempt to lookup an object in the second list with the same key.
How does this sound? Is there a better way of achieving this??
All help is much appreciated!
UPDATE:
Okay, so actually I need a bit more. Upon finding a match, I want to overwrite properties L1Obj.x, L1Obj.y, L1Obj.z with those of L2Obj. HashSet sounds great for finding that matches, but if I'm right it doesn't actually allow me to access these matches.
What can I do about this?
Do the objects you want to look at implement equals(Object)
and hashCode()
that only take into account the fields you care about? If so, you can create a new HashSet
from the first list, and then call retainAll()
passing in the second list.
If they don't implement equals(Object)
and hashCode()
with respect to the properties you care about, you can create a TreeSet
and pass in a Comparator
that looks at the properties you care about.
Rather than use the String repesntation, use the equals()
method a HashSet as so:
class MyObj {
Property a;
Property b;
Property c;
public boolean equals(Object o) {
// use == if Property is primitive, like int or something
return o instanceof MyObj && a.equals(o.a) && b.equals(o.b) && c.equals(o.c);
}
// edit - when you override equals, also override hashcode
public int hashCode() {
return a.hashCode() ^ b.hashCode() ^ c.hashCode();
}
public String toString() {
return a.toString() + " " + b.toString() + " " + c.toString();
}
}
// later in your main method
Set<MyObj> objSet = new HashSet<MyObj>();
for(MyObj o : list1) objSet.add(o);
for(MyObj o : list2) if(objSet.contains(o)) System.out.println(o + " is a match!");
You can do one thing. Have two lists with these objects and override the equals method of the class to which these objects belong. Your equals method should look like
@Override
public boolean equals(Object obj)
{
return (this.a == obj.a && this.b == obj.b && this.c == obj.c)
}
Also remember, once you override equals method, you need to override int hashCode() method as well.
One thing to note is while implementing hashCode() is that 2 equal objects will have same hashCode, while the converse is not true.
I don't know if I thinking to easy but I would try it like that:
Override the equals method of the object to implement your comparison to check if it is the same object
Then I would iterate over the first list and check with the contains method if the object is also contained in the second list.
Then I would iterate through the second list and check if the object is also in the first list and not already in the result list.
The object in question should implement the boolean equals(Object)
method. E.g.:
L1Obj.equals(L2Obj);
You could overload that method so that you can implement the equality operations that you want.
精彩评论