insict
insict

Reputation: 881

LinkedHashSet remove duplicates object

I have simple question to you, I have class Product that have fields like this:

private Integer id;
private String category;
private String symbol;
private String desc;
private Double price;
private Integer quantity;

I want to remove duplicates item from LinkedHasSet based on ID, e.g Products that have same ID but diffrent quantity will be add to set, I want to remove (update) products with same ID, and it will by my unique id of object, how to do that?

e.g Product: id=1, category=CCTV, symbol=TVC-DS, desc=Simple Camera, price=100.00, quantity=1 Product: id=1, category=CCTV, symbol=TVC-DS, desc=Simple Camera, price=100.00, quantity=3

won't be added to set

my code:

    public void setList(Set<Product> list) {
    if(list.isEmpty()) 
        this.list = list;
    else {
        this.list.addAll(list);
        Iterator<Product> it = this.list.iterator();
        for(Product p : list) {
            while(it.hasNext()) {
                if(it.next().getId() != p.getId())
                    it.remove();
                    this.list.add(p);   
            }
        }
    }
}

Upvotes: 6

Views: 20569

Answers (5)

Adam Dyga
Adam Dyga

Reputation: 8906

I won't give you straight answer, but a couple of advices.

  1. If you want to put Product in a Set you need to implement its equals() and hashCode() methods.
  2. When implementing equals() you will have to decide what "equality" for a Product means, (Set can contain only one instance in terms on "equality"). For instance, if two Product instances are "equal" is it enough if they have the same ID or should we also take quantity into account?. It's not easy to answer this question in your case, but please read on.
  3. Normally in situation like this only ID is taken into account. In that case you shouldn't have two Product instances in memory with different quantities, because one of them would represent a state that is incorrect (ie. particular product's quantity can be either 1 or 3, not both at a time).
  4. I think the design is not fully correct. Product class in your case represents a general product description (including price), so quantity doesn't really fit there. If someone can order a couple of copies of Product I think you should create another class such as Order or OrderLine which specifies what product is ordered and the corresponding quantity, eg:

    class OrderLine {
      private Product product;
      private Integer quantity; 
    }
    

    With design like this it's easy to answer question from point 2. Product.equals() should compare the ID only, and OrderLine.equals() both the product (ID) and quantity.

Upvotes: 2

Bimalesh Jha
Bimalesh Jha

Reputation: 1504

As others have already said, you will need to implement (override) equals(), hashCode() and (prefarably) compareTo() from Comparable interface. These methods, if not implemented correctly can lead to unexpected runtime behavior. Hard to debug issues. Hence, I suggest you use Apache Commons EqualsBuilder, HashcodeBuilder and ComparableBuilder to implement these methods. An example of how to use Apache Commons builder can be seen in this link http://www.javaworld.com/community/node/1859

Upvotes: 0

Kevin Bowersox
Kevin Bowersox

Reputation: 94459

The code seems to be adding to the list twice. Once during the addAll() call then once again during the iteration. In this case I believe the second iteration would suffice. The comparison should also be modified to use equals instead of ==

public void setList(Set<Product> list) {
    if(list.isEmpty()) 
        this.list = list;
    else {
        //this.list.addAll(list); Do not add all
        Iterator<Product> it = this.list.iterator();
        for(Product p : list) {
            while(it.hasNext()) {
                if(it.next().getId().equals(p.getId()))
                {
                    this.list.add(p);
                }   
            }
        }
    }
}

Upvotes: 0

Ivaylo Strandjev
Ivaylo Strandjev

Reputation: 70929

I would suggest you implement your own hash function in a way that it hashes elements with equal ID-s with the same code. This will solve your issue, without you having to code it explicitly.

Upvotes: 1

Andrzej Doyle
Andrzej Doyle

Reputation: 103797

All Set implementations remove duplicates, and the LinkedHashSet is no exception.

The definition of duplicate is two objects that are equal to each other, according to their equals() method. If you haven't overridden equals on your Product class, then only identical references will be considered equal - not different instances with the same values.

So you need to add a more specific implementation of equals (and hashcode) for your class. For some examples and guidance, see Overriding equals and hashcode in Java. (Note that you must override hashcode as well, otherwise your class will not behave correctly in hash sets.)

Upvotes: 18

Related Questions