Can't get value for object from Hashmap even though it returns the same hashcode
// 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;
}
}
source to share
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.
source to share
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.
source to share