Reputation: 21
So I have an arraylist basket that stores items, each item is made out of the name of the item and the price of the item fields. As you can see there's two sugar with same price. I want my code to print every single item with the amount of time its repeated.
What I want it to do is this: Count the duplicate values
2 x Sugar for 100
1 x Cake for 75
1 x Salt for 30
1 x Fanta for 50
My Item class toString's method is
public String toString(){
return name + " for " + price;
}
basket = new ArrayList<Item>();
basket.add(new Item("Sugar", 100));
basket.add(new Item("Sugar", 100));
basket.add(new Item("Cake", 75));
basket.add(new Item("Salt", 30));
basket.add(new Item("Fanta", 50));
HashSet<Item> set = new Hashset(basket)
for (Item item : set ){
System.out.println(Collections.frequency(basket, item) + " x" + item);
}
But what it does is...
1 x Sugar for 100
1 x Sugar for 100
1 x Cake for 75
1 x Salt for 30
1 x Fanta for 50
so i'm thinking that its comparing the toStrings but the repeated ones are not equalling to true.
please help.
This is my first ever post and don't really know the exact rules of posting
Upvotes: 0
Views: 1644
Reputation: 21
This is what my code was missing in my Item class; You need to override the equals and hashcode methods that every objects have by default. This will allow you to compare two objects by their state. object A with to private fields e.g. int field and a String field with object B. If both fields are the same there return value will be true
@Override
public boolean equals(Object obj){
//check for null
if(this == null){
return false;
}
//make sure obj is a item
if(getClass() != obj.getClass()){
return false;
}
//cast obj as an item
final Item passsedItem = (Item) obj;
//check fields
if(!Objects.equals(this.name, passsedItem.name)){
return false;
}
if(!Objects.equals(this.price, passsedItem.price)){
return false;
}
return true;
}
/**
* Override hashcode method to be able to compare item state to see if they are the same
* @return
*/
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + Objects.hashCode(this.price);
return hash;
}
Upvotes: 0
Reputation: 11
It would be better to use a Map in this scenario. First, make sure you are implementing the equals(Object) and hashCode() methods in your Item object, then putting each unique Item into the map with a value of an AtomicInteger with base value 1. Before putting in the object in the map you should check to make sure the item is not already in the map, if it already exists in the map, get the AtomicInteger and increment it.
Something like this..
Map<Item, AtomicInteger> quantitiesByItem = new HashMap<>();
for (Item item : listOfItems) {
if (!quantitiesByItem.contains(item)) {
quantitiesByItem.put(item, new AtomicInteger(1));
} else {
quantitiesByItem.get(item).incrementAndGet();
}
}
A HashSet actually prevents duplicates so would only be useful in a scenario where you are trying to strip duplicate records.
EDIT: You could also use Collections.frequency but you need to implement equals(Object) and hashCode() in your Item object otherwise the objects are determined to be different because they aren't the exact same object. You will also need to stop adding all your values from your list to a set and instead just pass your List object to Collections.frequency method.
Upvotes: 1