Can't get value for object from Hashmap even though it returns the same hashcode

enter image description here// Can't get the value of an object in the hashmap after overriding its hashcode // This is the item class where I generate hascode based on the item name

 public class Item {
                    private String name;
                    private Long id;
                    private double price;
                //Constructor
                    public Item(String name, Long id, double price) {
                        this.name = name;
                        this.id = id;
                        this.price = price;
                    }

                    public String getName() {
                        return name;
                    }

                    public void setName(String name) {
                        this.name = name;
                    }

                    public Long getId() {
                        return id;
                    }

                    public void setId(Long id) {
                        this.id = id;
                    }

                    public double getPrice() {
                        return price;
                    }

                    public void setPrice(double price) {
                        this.price = price;
                    }
                //Generating hashcode based on name comparing if item id are //same        
                    @Override
                    public int hashCode() {
                        return name.hashCode();
                    }
                    @Override
                    public boolean equals(Object obj) {
                        return ((Item) obj).id ==(id);
                    }

                    @Override
                    public String toString() {
                        return "Item {" +
                                " name='" + name + '\'' +
                                ", id=" + id +
                                ", price=" + price +
                                '}';
                    }
        //Here there are items but when i pass the exact same item with exact //credentials i get null while checking how many items are there using Hashmap.
                public class Warehouse {
                    Map<Item, Integer> itemList = new HashMap<>();
                    List<Drone> drones = new ArrayList<>();
                    private Drone drone;
                    private String sourceAddress;
                    private Address address;

                    public Warehouse(Address address) {
                        this.address = address;
                        Item item = new Item("PlayStation 4 pro", (long) 100, 42000);
                        Item item1 = new Item("X box one S", (long) 200, 40000);
                        Item item2 = new Item("Apple Macbook Pro", (long) 500, 82000);
                        Item item3 = new Item("Dell Xps Laptop", (long) 1000, 92000);
                        Item item4 = new Item("iPhone 7 plus", (long) 2000, 72000);

                        itemList.put(item, 10);
                        itemList.put(item1, 20);
                        itemList.put(item2, 40);
                        itemList.put(item3, 50);
                        itemList.put(item4, 20);

                    }

                    public Drone getDrone() {
                        return new Drone();
                    }

                    public void setDrone(Drone drone) {
                        this.drone = drone;
                        System.out.println("Drone # " + drone.getDroneID() + " has arrived at the warehouse " + address);
                    }

                    public Address getAddress() {
                        return address;
                    }


                    public ArrayList<Item> getItemList() {
                        return (ArrayList<Item>) itemList;
                    }
                //Setting the item
                    public void setItem(Item item) {
                        Integer num = itemList.get(item);
                        if (num == null) {
                            num = 0;
                        }
                        this.itemList.put(item, ++num);

                    }

      

// I run into a problem here, if I ask for a hash file for the same item that returns me null, Item even returns the same hashcode

                    public Item removeItem(Item item) {
                        Integer num = itemList.get(item);
                        //## Issue is i get null in num 
                        if(null!= num||num!=0  ){
                            itemList.put(item,num-1);
                        }
                        System.out.println(item);
                        return item;
                    }

            }

      

+3


source to share


2 answers


Your object is hashCode

using a property name

, but yours is equals

using a property id

. This violates the contract. Objects that equals

return true must have the same hashCode

.

HashMap

uses both hashCode

and equals

to find the key. It first finds the cell in HashMap

the stem hashCode

. It then scans through all the entries in the cart using equals

to find the key you are looking for. If it hashCode

does not match equals

, the two objects that you think are equal may be mapped to different cells, so using the map.contains(key)

key stored in to find Map

it will fail.

I think it would be wiser to use it id

as equality criteria, so I would write:

@Override
public int hashCode() {
    return id.hashCode();
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (!(obj instanceof Item))
        return false;
    return ((Item) obj).id.equals(id);
}

      

Note that I used s equals

to compare id

. Comparing objects with ==

( Long

in your case) is usually wrong.

Also, you might want to make your method equals

safer by checking the type obj

before sending it to Item

and returning false if the type is not the same.



PS based on your new code, you have another problem:

This condition:

if(null!= num||num!=0  )

      

will either be true (if num != null

) or cast a NullPointerException

(if num

is null

).

Therefore it will put Item

in Map

if it is already in Map

. It's not clear what the desired logic is, but it doesn't seem right.

+5


source


The decision about where / in which to write comes based on your hashcode

. But there may be many entries in this bucket.

So, it equals

is called to identify the record you are interested in. Since hashcode

and are equals

not related (different properties) that introduce inconsistency.

So, let's say you have this:



  EntryA (hashCode = 42, id = 2)
  EntryB (hashCode = 44, id = 2)

      

These entries equal

are based on id

; but since they are different hashcodes

, they will move to different cells in the HashMap in different parts.

So now you will have two identical entries (according to equals) in the Map - which is why the hashcode and equals must be consistent with each other.

+3


source







All Articles