Reputation: 75673
I have a Set
of expensive objects.
These objects have IDs and the equals
uses these IDs for equality.
These objects' type has two constructors; one for the expensive object, and one that just sets the ID.
So I can check if a particular ID is in the Set
using Set.contains(new Object(ID))
.
However, having determined the object is in the set, I cannot get the object instance in the set.
How can I get the exact object that the set contains?
Upvotes: 7
Views: 4757
Reputation: 6706
Consider using the UnifiedSet
class in Eclipse Collections. It implements the Pool
interface in addition to Set
. Pool
adds Map
-like API for put and get. Pool
is more memory efficient than Map
since it doesn't reserve memory for values, only keys.
UnifiedSet<Integer> pool = UnifiedSet.newSet();
Integer integer = 1;
pool.add(integer);
Assert.assertSame(integer, pool.get(new Integer(integer)));
Note: I am a committer for Eclipse Collections.
Upvotes: 4
Reputation: 1429
Here is one hack you can do to get what you want. Basically when you use contains to search within a hashset, the equals method of the object you're looking for will be called when hash codes match. Assuming you're dealing with objects of your own, or ones you can extend, it's trivial to set a 'beacon signal' ;) static field of the class with the reference that was just equated. And here you go, you can call contains and if true is returned, retrieve the object ;)
P.S. don't judge me
import java.util.HashSet;
import java.util.Set;
public class BecauseWhyNot {
public static void main(String[] args) {
Set<Poop> sewage = new HashSet<Poop>();
set.add(new Poop("Morning Delight"));
set.add(new Poop("Hangover Doodle"));
System.out.println("Contains Fire Drill?: "
+ set.contains(new Poop("Fire Drill")));
System.out.println("Contains Morning Delight?: "
+ set.contains(new Poop("Morning Delight")));
if (Poop.lastlySmelled != null)
System.out.println("It's you lucky day: " + Poop.lastlySmelled);
else
System.out.println("Sorry, try again ;)");
}
public static class Poop {
static Poop lastlySmelled = null;
String description;
Poop(String desc) {
description = desc;
}
@Override
public int hashCode() {
return 900913 * description.hashCode();
}
@Override
public boolean equals(Object obj) {
lastlySmelled = (Poop) this;
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
Poop other = (Poop) obj;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
return true;
}
public String toString() {
return "Poop: " + description + "!";
}
}
Upvotes: 1
Reputation: 14243
You could use a FilterIterator from Apache Commons Collections:
Predicate eq = new EqualPredicate(new Object(ID));
FilterIterator filter = new FilterIterator(set.iterator(), eq);
Object o = (Object) filter.next();
Obviously this is going to be an expensive way of accessing it, but if you're fixed on using a Set
, you will have to iterate it at some point.
Upvotes: 0
Reputation: 533820
If you want to get
from a collection you should use a Map.
(Note most Set implementations are wrappers for a Map)
Map<Key, Value> map = new ....
Value value = map.get(new Key(ID));
In your case, the key and value can be the same type but that is generally a bad idea as keys, like elements of a set, should be immutable.
Upvotes: 6
Reputation: 19187
If HashMap
with id's as keys wouldn't work, then I'd use a HashMap
with your object both as key and value.
Upvotes: 2