1

I creating a program to emulate a restaurant bill, this contains two classes, Diner and Food Item.

Item class:

package dinersbill;

public class Item {

    private String name;
    private double price;
    private int buyerCount = 0;

    public Item(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    public int getBuyerCount() {
        return buyerCount;
    }

    public void incrementBuyerCount() {
        buyerCount += 1;
    }

}

Diner class:

package dinersbill;

import java.util.ArrayList;

public class Diner {

    private String name;
    private ArrayList<Item> itemList = new ArrayList<Item>();

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

    public String getName() {
        return name;
    }

    public ArrayList<Item> getItemList() {
        return itemList;
    }

    public void addItem(Item foodItem) {
        itemList.add(foodItem);
        foodItem.incrementBuyerCount();
    }

    public double getPrice() {
        double total = 0;
        for(Item item : itemList) {
            total += item.getPrice() / item.getBuyerCount();
        }
        return total;
    }

}

The Diner class holds an ArrayList of Item objects, as one Diner may purchase multiple Items. Finally, I have the top level class which holds an ArrayList of Diner objects:

package dinersbill;

import java.util.ArrayList;

public class DinerList {

    private ArrayList<Diner> diners = new ArrayList<Diner>();

    public DinerList(ArrayList<Diner> diners) {
        this.diners = diners;
    }

    public ArrayList<Item> getDinerItems() {
        ArrayList<Item> itemList = new ArrayList<>();
        for(Diner d : diners) {
            for(Item i : d.getItemList()) itemList.add(i);
        }
        return itemList;
    }

} 

How would I go about altering the getDinerItems method in DinerList to only return objects if they appear once? I am having an issue with Items appearing more than once in this list as a single item may be purchased by multiple Diners.

For example:

private static DinerList diners = new DinerList(dinerList);

public static void main(String[] args) {
    Diner diner1 = new Diner("John");
    Diner diner2 = new Diner("Tom");

    dinerList.add(diner1);
    dinerList.add(diner2);

    Item item1 = new Item("Pizza", 5);
    Item item2 = new Item("Icecream", 10);

    diner1.addItem(item1);
    diner2.addItem(item1);
    diner2.addItem(item2);

    for(Item i : diners.getDinerItems()) {
        System.out.println(i.getName());
    }


}

Actual Output:

Pizza Icecream Pizza

The Output I would like:

Pizza Icecream

3
  • Read about Sets. Commented Mar 21, 2015 at 12:42
  • Could you clarify what getDinerItems() should do? Should it return a collection of items where a given item only appears once (with varying "buyer counts") or should it only return the items that appear once in all diners' item lists? The latter is what your question is actually implying (which does not make sense really). Commented Mar 21, 2015 at 12:50
  • I have added additional explanation to the bottom of my post, I hope this makes it clearer. It should return items where a given item only appears once. (with varying "buyer counts") Commented Mar 21, 2015 at 12:56

5 Answers 5

1

Use Set(HashSet Implementation) instead of arraylist which is designed to avoid duplicate elements

Sign up to request clarification or add additional context in comments.

Comments

1

The easiest way is to delegate the functionality of removing duplication to a Set collection.

This requires the equals() and hashCode() methods to be implemented correctly and make the Item immutable class.

Comments

0

Based on your example application, it looks like you only want to return the distinct item names from getDinerItems(). If so, just change the method to

public Set<String> getDinerItems() {
  Set<String> itemNames = new HashSet<String>();
  for (Diner d : diners) {
    for (Item i : d.getItemList()) {
      itemNames.add(i.getName());
    }
  }
  return itemNames;
}

However, if the buyer counts matter to you (and they probably do), you need changes also in your Diner class:

You need to redesign your Diner class so that it can only hold one Item with a given name (assuming that the "name" uniquely identifies an item and all items with the same name have the same price in your domain model). This will require changing the collection of items in Diner to a Map:

private Map<String, Item> items = new HashMap<String, Item>();

You also need to modify the logic in addItem() to something like this:

public void addItem(Item foodItem) {

    if (!items.contains(foodItem.getName())) {
      items.put(foodItem.getName(), foodItem);          
    }
    items.get(foodItem.getName()).incrementBuyerCount();
}

Finally, in getDinerItems(), you would sum up the buyer counts of all diners' items into a set of Items that gets returned.

Comments

0

My understanding of your question is that you wish to store a list of items for each diner and also store another list which holds the diners. And you want to remove duplicate entries. In essence, you need to use a Set rather than an ArrayList. A Set would automatically disallow you to store duplicates at the time of insertion, so the need to remove duplicate would not be there. You can use either HashSet or a TreeSet. Hope this helps. Regards Sandeep

Comments

-1

Shortest you can do

itemList = new ArrayList<Item>(new HashSet<Item>(itemList));

add above statement before return.

And also best option is to use Set

1 Comment

I don't think that this will change anything, because his model classes aren't overriding #equals and #hashCode. Therefore the set won't be able to identify the duplicates.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.