【问题标题】:Set stored duplicate records设置存储的重复记录
【发布时间】:2017-02-13 17:18:56
【问题描述】:

好的,这可能是一个简单的问题,但是当我读到 set 和我得到的回复时,我感到很困惑。

我正在从数据库中获取重复记录,并使用 set 为一个条件(代码)只存储一条记录以忽略剩余的重复记录。

Set<DiagnosisInfo> diagnosisInfoSet = patientDiagnosisHistoryRepository
                    .findBydiagnosisdesc(UUID.fromString(patientID.toUpperCase()));

我得到的回应是

 "diagnosisInfo": [
    {
      "diagnosisCode": "T49.1X6S",
      "diagnosisCodeDescription": "Underdosing of antipruritics, sequela"
    },
    {
      "diagnosisCode": "T49.1X6S",
      "diagnosisCodeDescription": "Underdosing of antipruritics, sequela"
    },
    {
      "diagnosisCode": "T49.1X6S",
      "diagnosisCodeDescription": "Underdosing of antipruritics, sequela"
    },
    {
      "diagnosisCode": "T49.1X6S",
      "diagnosisCodeDescription": "Underdosing of antipruritics, sequela"
    },
    {
      "diagnosisCode": "V09.20",
      "diagnosisCodeDescription": "Pedestrian injured in traffic accident involving unspecified motor vehicles*"
    },
    {
      "diagnosisCode": "V09.20",
      "diagnosisCodeDescription": "Pedestrian injured in traffic accident involving unspecified motor vehicles*"
    },
    {
      "diagnosisCode": "V09.20",
      "diagnosisCodeDescription": "Pedestrian injured in traffic accident involving unspecified motor vehicles*"
    },
    {
      "diagnosisCode": "E09.8",
      "diagnosisCodeDescription": "Drug or chemical induced diabetes mellitus with unspecified complications"
    },
    {
      "diagnosisCode": "E09.8",
      "diagnosisCodeDescription": "Drug or chemical induced diabetes mellitus with unspecified complications"
    },
    {
      "diagnosisCode": "E09.8",
      "diagnosisCodeDescription": "Drug or chemical induced diabetes mellitus with unspecified complications"
    },
    {
      "diagnosisCode": "E09.8",
      "diagnosisCodeDescription": "Drug or chemical induced diabetes mellitus with unspecified complications"
    },
    {
      "diagnosisCode": "E09.8",
      "diagnosisCodeDescription": "Drug or chemical induced diabetes mellitus with unspecified complications"
    }
  ]

正如我们所见,相同的诊断代码记录会显示多次,尽管它们是重复的。我想看到的响应如下

 "diagnosisInfo": [
    {
      "diagnosisCode": "T49.1X6S",
      "diagnosisCodeDescription": "Underdosing of antipruritics, sequela"
    },
    {
      "diagnosisCode": "V09.20",
      "diagnosisCodeDescription": "Pedestrian injured in traffic accident involving unspecified motor vehicles*"
    },
    {
      "diagnosisCode": "E09.8",
      "diagnosisCodeDescription": "Drug or chemical induced diabetes mellitus with unspecified complications"
    }
  ]

一个代码一个响应。我不知道我是否必须更改我的查询,或者关于 set 的一些事情。

【问题讨论】:

    标签: java collections set


    【解决方案1】:

    重点是:

    正如我们所见,相同的诊断代码记录虽然重复显示了多次。

    不,它们相同。您必须为您的类 DiagnosisInfo 实现正确的 equals()hashCode() 方法!

    为了判断两个对象是否“相同”; Set 实现将使用这些对象提供的 equals 方法。最有可能的是,您要么忘记在课堂上使用 @Override equals();您提供了一个导致false 的实现;即使对于那些你认为“相同”的对象。

    有关更多详细信息,请参阅here

    鉴于您的最新评论,您的逻辑似乎仍然倒退。你仍然认为你“知道”哪些对象是重复的,哪些不是。但是您认为重要。唯一重要的是您的 equals() 方法中的实现。 操作的结果决定了对象是否相等/相似;或者它们是否不同。

    所以:当你向一个类添加新字段时;并使用您的 IDE 重新生成这些方法,现在您对结果“不满意”;那么您的问题是您在生成过程中包含您实际上认为“不应该重要”的字段。代码按照您告诉它执行的操作。

    因此,真正的答案在这里:

    • 您应该退后一步,重新考虑您的对象模型。在生成 equals/hashCode 方法时,您不会创建/添加字段并包含(或不包含)它们,因为您可以这样做。不,您决定需要做什么;然后你就实现了。
    • 然后:这样的代码对于单元测试和 TDD 来说是完美的。您无需等待读取一些真实数据;不:您有各种单元测试来验证您的 equals 实现提供了预期的结果。然后,当您添加新内容或更改代码时,您会重新运行这些测试,它们会告诉您您破坏了哪些内容。

    【讨论】:

    • 感谢您的澄清。我完全忘记了我们必须重写 equals 和 hashCode 方法来比较两个对象的基础知识。
    • 我已经覆盖了 hashCode 和 Equals 方法,昨天它运行良好,没有重复。今天我在类中添加了更多字段并生成了 hashCode 和 Equals 方法,但它不起作用。有什么我想念的吗?我正在从 Eclipse 生成这些方法。
    • 感谢您的宝贵时间。我对你的两个否定问题投了赞成票。问题是我的要求发生了变化,我必须在类中添加几个字段并重新生成 hashCode 和 Equal 方法。根据您更新的答案,如果我稍后更新它,我得到它就像它不支持一样。那是对的吗?如果它不支持,那么我该如何控制这些重复记录?我是否必须编写手动 hashCode 和 equals 方法而不是通过 IDE 生成它们?
    • 重点是:您可以随时告诉您的 IDE 重新生成这些方法。但是,当您这样做时,需要了解哪些字段应该参与这些方法。 IDE 生成您告诉它生成的内容。仅当 IDE 无法生成您要查找的内容时,您才需要手动编写它们。如果您有更具体的问题,请考虑 A) 用更多内容增强您的问题;或 B) 提出一个新问题……在这两种情况下,请给我另一条评论……但我明天之前没有时间。
    • 好的,谢谢。我会更新我的问题。有时间的可以去看看:)
    【解决方案2】:

    是的,这就是 DiagnosisInfo 不覆盖 Equals 和 haschCode 时得到的结果

    您的 Set 不知道如何检查此对象的时间

    {
      "diagnosisCode": "V09.20",
      "diagnosisCodeDescription": "Pedestrian injured in traffic accident involving unspecified motor vehicles*"
    },
    

    还有这个

    {
      "diagnosisCode": "V09.20",
      "diagnosisCodeDescription": "Pedestrian injured in traffic accident involving unspecified motor vehicles*"
    },
    

    都是一样的……


    假设您调用的方法实现了HashSet&lt;E&gt;,那么源代码:

    /**
     * Adds the specified element to this set if it is not already present.
     * More formally, adds the specified element <tt>e</tt> to this set if
     * this set contains no element <tt>e2</tt> such that
     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
     * If this set already contains the element, the call leaves the set
     * unchanged and returns <tt>false</tt>.
     *
     * @param e element to be added to this set
     * @return <tt>true</tt> if this set did not already contain the specified
     * element
     */
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
    

    map.put 在哪里调用 putVal

    而 putval 使用 equals 和 hashcode...哈哈!

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }
    

    【讨论】:

    • 也感谢您的帮助。您建议的代码对我来说看起来太难理解了。对不起,我是个新手。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 2018-12-16
    • 1970-01-01
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多