无法从 Hashmap 获取对象的值,即使它 returns 具有相同的哈希码

Unable to get value for an object from Hashmap, even though it returns the same hashcode

//覆盖其hashcode后无法获取hashmap中对象的值 //这是我根据项目名称

生成hascode的项目class
 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);

                    }

//这就是我面临的问题,如果我查询 hashmap 中的相同项目,它 returns me null,Item even returns 相同的 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;
                    }

            }

您的对象的 hashCode 使用了 name 属性,但是您的 equals 使用了 id 属性。这违反了合同。 equals returns 为真的对象必须具有相同的 hashCode.

HashMap 使用 hashCodeequals 来定位键。首先,它根据 hashCodeHashMap 中定位一个 bin。然后它使用 equals 遍历 bin 中的所有条目以找到您要查找的密钥。当 hashCode 不匹配 equals 时,您认为相等的两个对象可能会映射到不同的 bin,因此使用 map.contains(key) 查找存储在 Map 中的键会失败。

我认为用id作为平等的标准更有意义,所以我会写:

@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);
}

请注意,我使用 equals 来比较 id。将对象与 ==(在您的情况下为 Longs)进行比较通常是错误的。

此外,您可能希望在将 obj 转换为 Item 之前检查其类型,如果类型不正确则返回 false,从而使 equals 方法更安全匹配。

P.S。根据您的新代码,您还有另一个问题:

这个条件:

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

要么为真(如果 num != null),要么抛出一个 NullPointerException(如果 numnull)。

因此,如果它已经在 Map 中,它只会将 item 放在 Map 中。不清楚所需的逻辑是什么,但看起来不对。

where/which 个条目的决定是根据您的 hashcode 做出的。但是该存储桶中可能有 许多 个条目。

所以调用 equals 来识别您感兴趣的条目。由于 hashcodeequals 是不相关的(不同的属性),这会导致不一致。

所以假设你有这个:

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

这些条目 equal 基于 id;但由于它们有不同的 hashcodes,它们将在 HashMap 的不同部分进入 不同的桶

所以现在您将在 Map 中有两个相同的条目(根据 equals)——这就是为什么 hashcode 和 equals 必须 彼此一致.