I know this question has already been asked on SO a couple of times, but I still haven't found a satisfying solution, and I'm unsure which way to go. The question is:
Why doesn't the Java library provide HashSet.get(Object o) and HashMap.getKey(Object o) methods that return the actual instance in the map providing an equal instance? Example:
// Retrieve a house with ID=10 that contains additional information like size,
// location and price.
houses.get(new House(10));
I think the best answer can be found here. So here's a mixture of answers that I'm aware of:
- Why would you need the instance when you already have it? It doesn't make sense to try to get the same object you already have. The object has an identifier (which controls it's equality to other Foo types) plus any number of other fields that do not contribute to it's identity. I want to be able to get the object from the Set (which includes the extra fields) by constructing an 'equal' Foo object (text is taken from one of the comments). -> no answer 
- Iterate the - Collectionand search for the instance using- equals(). This uses linear search and is extremely slow in big collections. -> bad answer
- Use a HashMap instead of a HashSet I don't need a map and I think it's not adequate to return a map in a method like - getHouses(). The getter should return a- Setand not a- Map.
- Use - TreeSet.ceiling- don't know
- This hacky code below (Java 8 - HashSetonly) uses reflection and provides the missing functionality. I did not find something like this in other answers (no surprise). This could have been an acceptable solution if the target Java version is defined and future Java versions would finally provide such a method, now that we have- defaultmethods for interfaces. One could think of- default E get(E o){stream().filter(e->e.equals(o)).findAny().orElse(null);}
// Alternative: Subclass HashSet/HashMap and provide a get()/getKey() methods
public static <T> T getFromSet(HashSet<T> set, T key) throws Exception {
    Field mapField = set.getClass().getDeclaredField("map");
    mapField.setAccessible(true);
    HashMap<T, Object> map = (HashMap) mapField.get(set);
    Method getNodeMethod = map.getClass().getDeclaredMethod("getNode",
            int.class, Object.class);
    getNodeMethod.setAccessible(true);
    return (T) ((Map.Entry) getNodeMethod.invoke(map, key.hashCode(),
            key)).getKey();
}
Here are the questions:
- Is the best solution the use of HashMap<House, House>instead ofHashSet<House>?
- Is there another library out there that provides this functionality and supports concurrent access?
- Do you know of a bug addressing this feature?
Similar questions on SO:
 
     
     
    