Jinjinbug
Jinjinbug

Reputation: 15

Counting Number of occurences of an element in a List

I am trying to make a list where I would add items in to my shopping cart, then at check out it would show how many occurrences of items there are by using a HashMap.

public class ShoppingCart 
{
    private ArrayList<Items> ShoppingCart;

    public ShoppingCart()
    {
        ShoppingCart = new ArrayList<Items>();
    }

    public void addItems(Items newItems)
    {
        ShoppingCart.add(newItems);
    }

    public ArrayList<Items> getShoppingCart()
    {
        return ShoppingCart;
    }

    public void CheckOut()
    {
        for(int i = 0; i < ShoppingCart.size(); i++)
        {
                HashMap<String, Integer> itemsMap = new HashMap<String, Integer>();
                int a = 1;

                if (itemsMap.containsKey(ShoppingCart.get(i).getName()))
                {
                    itemsMap.replace(ShoppingCart.get(i).getName(), a, a++);
                } 
                else 
                {
                    itemsMap.put(ShoppingCart.get(i).getName(), a);
                }
            System.out.println(a +"x "+ShoppingCart.get(i));
        }
    }

and my items are created with

public class Items 
{
    private String name;

    public Items (String name)
    {
        this.name = name;
    }

    public String toString()
    {
        return name;
    }

    public String getName()
    {
        return name;
    }

}

In the Main, I would create Items, and Add them to the shopping cart, then ShoppingCart.CheckOut(); my items.

However, if I add 4 "White Bread" like so,

    Items bread = new Items("White Bread");

    ShoppingCart ShoppingCart = new ShoppingCart();

    ShoppingCart.addItems(bread);
    ShoppingCart.addItems(bread);
    ShoppingCart.addItems(bread);
    ShoppingCart.addItems(bread);

I get

1x White Bread
1x White Bread
1x White Bread
1x White Bread 

instead of

4x White Bread

What am I doing wrong?

Upvotes: 1

Views: 99

Answers (4)

SeanKelleyx
SeanKelleyx

Reputation: 1155

I believe your problem is that you are creating a new hashmap for every item in your shopping list, try this instead:

    public void CheckOut()
{
    HashMap<String, Integer> itemsMap = new HashMap<String, Integer>();
    for(int i = 0; i < ShoppingCart.size(); i++)
    {
        if (itemsMap.containsKey(ShoppingCart.get(i).getName()))
        {
            itemsMap.put(ShoppingCart.get(i).getName(), itemsMap.get(ShoppingCart.get(i).getName())+1);
        } 
        else 
        {
            itemsMap.put(ShoppingCart.get(i).getName(), 1);
        }
    }
    Iterator it = itemsMap.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry pair = (Map.Entry)it.next();
        System.out.println(pair.getValue()+"x " + pair.getKey() );
    }
} 

Upvotes: 0

Ulises
Ulises

Reputation: 9625

2 main problems: - HashMap is created on each iteration, so you loose whatever you had in the map before. - Your system out statement in within the FOR, so you'll get as many lines printed as elements you have in the loop.

Why not use A map to store the items like this?

public class ShoppingCart {

Map<Items, Integer> shoppingCart = new HashMap<>();

public ShoppingCart() {
}

public void addItems(Items newItem) {
    int count = shoppingCart.containsKey(newItem) ? shoppingCart.get(newItem) : 0;
    shoppingCart.put(newItem, ++count);
}

public List<Items> getShoppingCart() {
    return shoppingCart.keySet()
        .stream()
        .flatMap(item -> Collections.nCopies(shoppingCart.get(item), item).stream())
        .collect(Collectors.toList());
}

public void CheckOut() {
    for (Map.Entry<Items, Integer> entry : shoppingCart.entrySet()) {
        System.out.println(String.format("%dx %s", entry.getValue(), entry.getKey().getName()));
    }
}

public static class Items
{
    private String name;

    public Items (String name)
    {
        this.name = name;
    }

    public String toString()
    {
        return name;
    }

    public String getName()
    {
        return name;
    }

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

    @Override
    public boolean equals(Object obj) {
        if(obj instanceof Items) {
            return name.equals(((Items)obj).getName());
        }
        return false;
    }
}

public static void main(String[] args) {
    Items bread = new Items("White Bread");

    ShoppingCart ShoppingCart = new ShoppingCart();

    ShoppingCart.addItems(bread);
    ShoppingCart.addItems(bread);
    ShoppingCart.addItems(bread);
    ShoppingCart.addItems(bread);

    ShoppingCart.CheckOut();
    System.out.println(ShoppingCart.getShoppingCart());
}

}

Upvotes: 0

Zbynek Vyskovsky - kvr000
Zbynek Vyskovsky - kvr000

Reputation: 18825

Count them in advance and print the sum:

    Map<String, Integer> itemsMap = new LinkedHashMap<String, Integer>();    
    for(int i = 0; i < ShoppingCart.size(); i++)
    {

            itemsMap.merge(ShoppingCart.get(i).getName(), 1, (old, set) -> old+set);
    }

    for (Map.Entry <String, Integer> e: itemsMap.entrySet ()) {
        System.out.println(e.getValue ()+"x "+e.getKey ());
    }

Upvotes: 0

Eran
Eran

Reputation: 393771

Change

itemsMap.replace(ShoppingCart.get(i).getName(), a, a++);

to

a = itemsMap.get(ShoppingCart.get(i).getName()); // in order to increment the 
                                                 // current counter value
itemsMap.replace(ShoppingCart.get(i).getName(), a, ++a);

Using post decrement (a++) doesn't modify the value in the Map, since a++ returns the original value of a.

In addition, the HashMap should be initialized outside the loop. Otherwise it will always contain just one element.

Upvotes: 5

Related Questions