java LinkedHashSet 删除重复对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14748095/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 17:15:57  来源:igfitidea点击:

LinkedHashSet remove duplicates object

javacollectionsset

提问by insict

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

我有一个简单的问题要问你,我有类 Product 有这样的字段:

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?

我想根据 ID 从 LinkedHasSet 中删除重复项,例如,具有相同 ID 但数量不同的产品将被添加到集合中,我想删除(更新)具有相同 ID 的产品,它将通过我的唯一对象 ID,如何要做到这一点?

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

例如产品:id=1,类别=CCTV,符号=TVC-DS,desc=简单摄像机,价格=100.00,数量=1产品:id=1,类别=CCTV,符号=TVC-DS,desc=简单摄像机,价格=100.00,数量=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);   
            }
        }
    }
}

回答by Andrzej Doyle

All Setimplementations remove duplicates, and the LinkedHashSetis no exception.

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

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

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

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 mustoverride hashcodeas well, otherwise your class will not behave correctly in hash sets.)

所以你需要为你的类添加一个更具体的equals(and hashcode) 实现。有关一些示例和指导,请参阅在 Java 中覆盖 equals 和 hashcode。(请注意,您也必须覆盖hashcode,否则您的类在哈希集中的行为将不正确。)

回答by Adam Dyga

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

我不会给你直接的答案,而是给你一些建议。

  1. If you want to put Productin a Setyou need to implement its equals()and hashCode()methods.
  2. When implementing equals()you will have to decide what "equality" for a Productmeans, (Setcan contain only one instance in terms on "equality"). For instance, if two Productinstances are "equal" is it enough if they have the same IDor should we also take quantityinto 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 Productinstances 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. Productclass in your case represents a general product description (including price), so quantitydoesn't really fit there. If someone can order a couple of copies of ProductI think you should create another class such as Orderor OrderLinewhich 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) andquantity.

  1. 如果你想放入ProductaSet你需要实现它的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)数量。

回答by Ivaylo Strandjev

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.

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

回答by Kevin Bowersox

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 equalsinstead of ==

代码似乎两次添加到列表中。在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);
                }   
            }
        }
    }
}

回答by Bimalesh Jha

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

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