0

I am creating a JSP shopping basket, I have a class called Basket which has a HashMap with a Product object as a key and Integer for values, which will be the quantity of the product. However when I add a product to the basket, instead of that product's quantity being incremented, the product is just added again into the map. The hashcode of the product changes, but the product I add is the same object, they do not change. I would like to understand what is happening here.

Basket class add method:

   public void addItem(String pid) {
        addItem(db.getProduct(pid));
    }

    public void addItem(Product p) {
        if (p != null) {
            Integer quantity = items.get(p);
            if (quantity == null){
                quantity = 1;
                System.out.println("first time adding");
            }
            else quantity++;

            items.put(p, quantity);
            System.out.println("added product: " + p + " with quantity of " + quantity);
        }
    }

Basket.JSP:

<%@ page import="shop.Product" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %>
<jsp:useBean id='basket'
             scope='session'
             class='shop.Basket'
/>
<%
    String empty = request.getParameter("emptyBasket");
    if (empty != null) {
        basket.clearBasket();
        System.out.println("basket cleared");
    }
    String item = request.getParameter("addItem");
    basket.addItem(item);
%>
<html>
<body>
<% HashMap<Product, Integer> items = basket.getItems();

    for (Map.Entry<Product, Integer> p : items.entrySet()) {
        System.out.println(p.getKey().hashCode() + " " + p.getValue());
    }
%>

in viewProduct.JSP I have a link containing

href="basket.jsp?addItem=<%=product.PID%>

to get to the basket page.

So my main question is why is the map adding the same key?

Sean2148
  • 365
  • 1
  • 3
  • 13

1 Answers1

2

You likely need to implement a hashCode method in the Product class.

By default the hashCode implementation returns the object's location in memory. The result from the object's hashCode method is what is used by the HashMap to identify the object.

In this case each time the Product is retrieved from the database using db.getProduct(pid), its location in memory is likely different.

Due to this the call that HashMap uses to lookup if the Product exists is different and therefore the object is added again to the HashMap.

To avoid this a hashCode and equals method should be implemented in Product. In your case using something unique like the ProductID (pid) makes sense:

// Assuming pid is public
public int hashCode() {
  return this.pid;
}

public equals(Object object) {
  return this.pid == ((Product)object).pid;
}

For more info on how to implement a more-robust hashCode see https://stackoverflow.com/a/113600/9129020

jvandoorn
  • 71
  • 1
  • 5