开发者

If you have equals/hashcode based on int, what's the optimal way to match a "full" object from another collection?

开发者 https://www.devze.com 2023-04-07 12:25 出处:网络
Say you had this DTO class: public class MyObj{ private int id; private String displayName; private String backendData;

Say you had this DTO class:

public class MyObj{
 private int id;

 private String displayName;
 private String backendData;

 public boolean equals(Object obj){
  return id.equals(obj);
 }

 private int hashCode(){
  return id.hashCode();
 }
}

Lets say a user got to pick several instances of MyObj from a list that only showed the displayName and the id# is associated in the background. To save bandwidth, you don't send backendData. When they submit their selection back to you, the client just sends you the id#.

Now, you've maintained the list of original options server side in a Collection<MyObj>. The naive approach to geting the "full" object back from the collection would be to iterate through t开发者_JAVA技巧he Collection and call ".equals()" on every object. This scales in O(n) though :(

It seems like with constant time operations collections like HashSet, I should be able to retrieve an object in constant time, if I know it's identity. But HashSet only has a "contains()" method and doesn't return the object it found.

Any advice? As always, thanks a bunch stackOverFlow!


I assume id is unique across the collection?

You are almost there use a Map<Integer, MyObj> then map.get(id) is asymptotically constant time.


You're object doesn't work (because you can't call methods on primitive data types). Change your id into an Integer, and use it in a hashed collection.

Map<Integer, T> objectMap = ...;
Integer id = someidfromfrontend;
T anObj = objectMap.get(id);


hashCode is intended to just get a quick number for an object. equals should do a full comparison of all the fields that you want to verify for object equality.

public class MyObj
{
    private final Integer id;

    private String displayName;
    private String backendData;

    public boolean equals(Object obj)
    {
        final MyObj other;

        if(obj == null || obj.getClass() != MyObj.class)
        {
            return (false);
        }

        other = (MyObj)obj;

        if(!(displayName.equals(other.displayName))
        {
            return (false);
        }

        if(!(backendData.equals(other.backendData))
        {
            return (false);
        }

        return (true);
    }

    private int hashCode()
    {
        return id.hashCode();
    }
}

This assumes none of the fields can be null, it is a bit more complex in the if statements if they can be null.


Your question presents multiple issues IMHO: first off don't use the db id as a hash key, you could get in trouble if that thing is autogenerated. Second hashset/map use hashcode and equals methods to retrieve objects (when u use the getmethod). First the hashcode is used to quickly find the bucket where your object might be. Then if there were collisions in your hash collection and there s multiple objects in the in that bucket then equals will be used to retrive the object. So when u use get with an instance of your class here only the fields that are used in hashcode and equals need to have the correct value in order to retrieve your object. In this case if ur object has the right id (but wrong other field) it could be used to retrieve its counterpart with the otherfield populated. That or u can use a map.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号