LinkedHashSet删除重复对象

时间:2013-02-07 09:50:59

标签: java collections set

我有一个简单的问题,我有类产品有这样的字段:

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

我想根据ID删除LinkedHasSet中的重复项,例如具有相同ID但不同数量的产品将添加到设置中,我想删除(更新)具有相同ID的产品,并且它将由我的唯一ID对象,怎么做?

e.g 商品名:id = 1,类别= CCTV,符号= TVC-DS,desc =简单相机,价格= 100.00,数量= 1 商品名:id = 1,类别= CCTV,符号= TVC-DS,desc =简单相机,价格= 100.00,数量= 3

不会添加到设置

我的代码:

    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);   
            }
        }
    }
}

5 个答案:

答案 0 :(得分:13)

所有Set个实现都会删除重复项,LinkedHashSet也不例外。

复制的定义是两个彼此相等的对象,根据它们的equals()方法。如果您没有在equals类上覆盖Product,那么只有相同的引用才会被视为相同 - 而不是具有相同值的不同实例。

因此,您需要为您的班级添加equals(和hashcode)的更具体的实施方案。有关示例和指导,请参阅Overriding equals and hashcode in Java。 (请注意,必须覆盖hashcode,否则您的类在哈希集中的行为不正确。)

答案 1 :(得分:2)

我不会直截了当地给你答案,但有几条建议。

  1. 如果您想将Product放入Set,则需要实施其equals()hashCode()方法。
  2. 在实施equals()时,您必须决定 Product意味着的“相等”,(Set只能包含一个实例“平等”)。例如,如果两个Product实例“相等”,如果它们具有相同的 ID 就足够了,还是我们还应该考虑数量?在您的案例中回答这个问题并不容易,但请继续阅读。
  3. 通常在这种情况下,只考虑ID。在这种情况下,你不应该在内存中有两个Product个实例,其中quantities不同,因为其中一个实例代表一个不正确的状态(即特定产品的数量可以是1或3,不是两个一起)。
  4. 我认为设计并不完全正确。您的案例中的Product类代表一般产品说明(包括价格),因此quantity并不适合那里。如果有人可以订购几份Product我认为您应该创建另一个类,例如OrderOrderLine,它指定订购的产品和相应的数量,例如:

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

    通过这样的设计,您可以轻松回答第2点的问题。Product.equals()应仅比较ID,OrderLine.equals()产品(ID)数量。< / p>

答案 2 :(得分:1)

我建议你实现自己的哈希函数,使其具有相同ID-s的相同代码的哈希元素。这将解决您的问题,而无需您明确地对其进行编码。

答案 3 :(得分:0)

代码似乎是两次添加到列表中。在addAll()调用期间,再次在迭代期间再次调用。在这种情况下,我相信第二次迭代就足够了。还应修改比较以使用equals代替==

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);
                }   
            }
        }
    }
}

答案 4 :(得分:0)

正如其他人已经说过的那样,您需要在equals()界面中实现(覆盖)hashCode()compareTo()和(prefarably)Comparable。如果未正确实现,这些方法可能会导致意外的运行时行为。很难调试问题。因此,我建议您使用Apache Commons EqualsBuilderHashcodeBuilderComparableBuilder来实现这些方法。有关如何使用Apache Commons builder的示例,请参阅此链接http://www.javaworld.com/community/node/1859