开发者

equality of item in java hashset

开发者 https://www.devze.com 2023-03-25 02:46 出处:网络
I need to implement equals() method for an Item that may be put in a hashset of it\'s Maker.The Item can have fields as below

I need to implement equals() method for an Item that may be put in a hashset of it's Maker.The Item can have fields as below

class Item{
    private String isbn;
    private String name;
    private double price;
...
}

class Maker{
    private String name;
    private Set<Item> items;
    public Maker() {
        super();
        items = new HashSet<Item>();
    }
...
}

If I implement equals by comparing the three fields and write a hashCode() based on those fields,I will get wrong results when

1.add item to hashset
2.modify the price of item
3.try to find if item exists in hashset


@Override
public boolean equals(Object o){
    if(o == this){
        return true;
    }
    if (!(o instanceof Item)){
        return false;
    }
    Item a = (Item)o;
    if(hasSameName(a) && hasSameIsbn(a) && hasSamePrice(a)){
        return true;
    }
    else{
       return false;
    }
}

@Override
public int hashCode(){
    int hash = 41 + this.isbn.hashCode();
    hash = hash*41+ new Double(this.price).hashCode();
    hash = hash*41 + this.name.hashCode();
    return hash;
}

...
Set<Item> items = new HashSet<Item>();
Item item1 = new Item();
item1.setName("crys开发者_高级运维tal bird");
item1.setIsbn("1111");
item1.setPrice(120.5);

items.add(item1);

System.out.println(items.contains(item1));//returns true
item1.setPrice(177.0);
System.out.println(items.contains(item1));//returns false

What is the solution to overcome this?Should I make hashCode() depend only on isbn and assume that it will not change during the life of the item.

Any help appreciated

mark.


Yes, ISBN is a typical natural identifier - use only it for both equals(..) and hashCode()


The HashSet.add() method (which is basically HashMap.put() method) finds the best place on the self-maintained inner table according to the hashcode().

If you change the value of the item That is Key in HashMap so it will alter the hashcode() value resulting abnormal result.

You should only consider ISBN as a Key for object to keep things as simple as possible.

@Override
public boolean equals(Object o){
    if( o == null ){
        return false;
    }
    if(o == this){
        return true;
    }
    if (!(o instanceof Item)){
        return false;
    }
    Item a = (Item)o;
    if( hasSameIsbn(a) ){
        return true;
    }
    else{
       return false;
    }
}

@Override
public int hashCode(){
    return (41 + this.isbn.hashCode());
}


There's a golden rule somewhere at the API you may have missed:
The hashCode must not be changed while the object is in the HashMap/Set!

The HashMap/Set uses the hashCode to arrange and find objects in a faster way. So you need to provide a hashCode that won't change. The hashCode doesn't need to be unique in every case, but it will provide better access times if it is.

The solution was already suggested by others: Use the ISBN as the hashCode. I provides a a very good uniqueness and won't change!


Yes , as your price is a part of hashCode computation and which in tern evaluates to your equality of objects, as you set a different price it's hashcode changes and hence you can not find the same item. contains() method uses equals() to check if a collection is containing the same object or not, and since your price is a factor in equality check after you modify it just is not equal any more, hence contains() can not find it.

0

精彩评论

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