当前位置: 首页 > 知识库问答 >
问题:

树集存储重复的自定义对象

盖泽宇
2023-03-14

你好,我可能监督了一些事情,但事情是这样的
我有一个树集

class CustomObject implements Comparable<CustomObject> {

    String product;
    String ean;

    public CustomObject(String ean){
      this.ean = ean; 
      // product is getting set via setter and can be null
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        CustomObject that = (CustomObject) o;

        return ean.equals(that.ean);

    }

    @Override
    public int hashCode() {
        return ean.hashCode();
    }

    @Override
    public int compareTo(CustomObject another) {
        if(equals(another)) return 0;
        if(product != null && another.product == null) return -1;
        if(product == null) return 1;

        return product.compareToIgnoreCase(another.product);
    }
}

现在我有一个添加新对象的函数。

private final TreeSet<CustomObject> productCatalog;

public void addObject(SomeData tag) {
    CustomObject p = new CustomObject(tag.getEan());

    if (productCatalog.contains(p)) { // <-- This checks only one entry of the Set.
        for (CustomObject temp : productCatalog) {
            if (temp.equals(p)) {
                p = temp; // I do stuff with that later which is irrelevent here
            }
        }
    } else {
       productCatalog.add(p);
    }   
} 

方法productCatalog。包含(p)compariable界面调用comparieto方法并进行比较。这里的问题是,它实际上只检查最后一个对象?在片场。因此,只存在一个唯一的CustomObject条目。

这是我使用调试器时的场景:

  1. productCatalog。包含(p)

如何让它不仅检查步骤4中的一个对象,而且检查集合中的所有当前对象。我错过了什么?

谢谢!

编辑:这些是一些示例数据。为了简单起见,SomeData标记基本上是一个字符串。

First run:

addObject("Ean1") // success added
addObject("Ean2") // success added
addObject("Ean3") // success added
addObject("Ean4") // success added

所有内容都添加到树集合中。

Second run:
addObject("Ean1") // failed already in the map
addObject("Ean2") // failed already in the map
addObject("Ean3") // failed already in the map
addObject("Ean5") // success added
addObject("Ean4") // success added
addObject("Ean4") // success added

出于测试目的,我根据Stringean手动设置产品名称。

public CustomObject(String ean){
      this.ean = ean; 
       switch(ean){
            case "Ean1": product = "TestProduct"; break;
            case "Ean2": product = "ProductTest";break;
            case "Ean3": product = "Product";break;
    }

TreeSet充当缓存。

Edit2:我就是这样解决的。

            for (CustomObject temp : productCatalog) {
                if (temp.equals(p)) {
                    p = temp; // I do stuff with that later which is irrelevent here
                }
            }

我删除了使用包含方法的if语句,因为在我的特殊情况下,它总是返回'1-1。现在我简单地迭代Set以正确使用equals'方法,因为TreeSet使用compareTo()检查Set中的每个元素。

Java文档声明如下

请注意,如果要正确实现set接口,set维护的顺序(无论是否提供显式比较器)必须与equals一致。(参见可比或比较器,了解与等于一致的精确定义。)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用其compareTo(或compare)方法执行所有元素比较,因此,从Set的角度来看,此方法认为相等的两个元素是相等的。即使集合的顺序与equals不一致,集合的行为也是定义良好的;它只是没有遵守Set接口的总合同。


共有1个答案

段阳夏
2023-03-14

主要问题:

compareTo如果产品和其他产品都返回1。产品为空。这是错误的,因为他们实际上是平等的。您可能忘记为较高的ean值设置产品名称,如“Ean4”和“Ean5”。

旧答案:

您的equalscompareTo实现不匹配。

equals对ean起作用,而compareTo对产品起作用。只有当你隐式地假设相同的ean意味着相等的乘积时,这才有效。如果在您的测试用例中这不是真的,那么结果将是错误的。

无论哪种情况,它都不是好的实现,因为这可能导致

 类似资料:
  • 根据Spark数据集介绍: 在我们期待Spark 2.0的时候,我们计划对数据集进行一些令人兴奋的改进,具体来说:。。。自定义编码器–虽然我们目前为各种类型自动生成编码器,但我们希望为自定义对象打开一个API。 并且尝试将自定义类型存储在中会导致以下错误: 无法找到存储在数据集中的类型的编码器。导入sqlC支持原始类型(Int、String等)和产品类型(case类)ontext.implicit

  • 如果你需要提供自定义文件存储 – 一个普遍的例子是在某个远程系统上储存文件 – 你可以通过定义一个自定义的储存类来实现。你需要遵循以下步骤: 1. 你的自定义储存类必须是django.core.files.storage.Storage的子类: from django.core.files.storage import Storage class MyStorage(Storage):

  • 我有一个Employee类有2个属性id和name。我正在重写hashcode和equals方法,如下所示。 Employee.java: 现在我有了一个测试类,我正在创建一个名为“Chris Gayle”的employee类的对象,并将其添加到HashSet中。之后,我将这个现有的employee对象的名称修改为“Kieron Pollard”,并将这个修改后的employee对象再次添加到Ha

  • 在我的项目中有几个实体具有相同的属性(对于示例'name'),所以,有可能创建一个存储库,其中使用自定义的select(实体)?因此,我从JpaRepository扩展了我的存储库,我扩展了MyCustomJpaRepository,MyCustomJpaRepository也扩展了JpaRepository,使其能够从JpaRepository授予基本功能? TKS

  • 我有以下对象需要存储在Cassandra中。我需要使用UDT还是有其他方法来存储对象。我需要最终使用存储库方法从spry-boot应用程序存储它。

  • 我正在尝试创建一个框,其中包含标题、正文(消息)、确定选项。 我如何将它们逐行分开(我的意思是由三部分的行分开)? 这是我正在使用的代码: