【问题标题】:How create Set with unique Objects using data from Object to compare?如何使用来自 Object 的数据创建具有唯一 Objects 的 Set 进行比较?
【发布时间】:2014-02-09 12:03:12
【问题描述】:

我有“Var”的TreeSet Var 是我自己的课程: http://pastebin.com/pXC4q2YB

我需要“字符串”对于 Var 的 TreeSet 是唯一的 因此集合中的任何 Var 都不能具有相同的“字符串”/“.getKey()”


我重写了 compareTo 方法,但是当我向该集合添加值时...

这仍然使用相同的键添加 Var...


我添加了一些调试...并且 compareTo 不针对某些组合运行。

一开始我有 8 个变量,接下来我会继续添加,但是每次 Var.replace 中的某些变量都不同,所以在第二次添加之后,我有 14 个元素......再过一些...... 30,然后结束,在集合中获得 30 Var 后,它会停止添加下一个。


PS:我使用该代码添加: http://pastebin.com/N372QUck

“变量”是 Var 的那个 Set

我经常使用此代码,因此不会很慢,8 个变量仅用于测试,如果有人愿意,可以增加约 50 个或更多。

【问题讨论】:

  • 使用Map 将键用作键并将值存储为new Var(replace, types) 之类的东西可能更容易,不是吗?这样,您的重复键和 compareTo 方法就不会出现问题,因为映射只能保存唯一键。想想吧!
  • @bobbel Ach...愚蠢的我...我尝试了一些 Map> 和其他奇怪且过于复杂的东西...但我什至不不要想那张简单的地图……谢谢!

标签: java set unique treeset


【解决方案1】:

TreeSet 的关键在于自然排序不仅用于 Object 比较,还用于沿 Tree 遍历。

你的 compareTo 方法确实存在很大的缺陷,用于实现自然排序。让我粘贴代码,然后指出它的缺陷:-

               @Override
                public int compareTo(Var var) {
                        if (var == null)
                                return 1;
                        return var.getKey().equals(this.getKey()) ? 0 : 1;
                }

Comparable 的 compareTo 方法中的违规行为:-

1) 实现者必须确保所有 x 和 y 的 sgn(x.compareTo(y)) == -sgn(y.compareTo(x))。 (这意味着如果 y.compareTo(x) 抛出异常,则 x.compareTo(y) 必须抛出异常。)

您上面的代码将允许多个空值,因为它返回 1 而不是抛出 NPE

2)TreeSet 是自平衡树。这意味着 treeSet 可能不会使用您认为相等的对象来进行比较,因为它会不断添加对象。Treeset 将按照 Comparable 定义的特定顺序遍历树或 Comparator 并根据 compareTo (-1,0,1) 返回的值在节点之间继续遍历。因此,在添加元素时,很有可能甚至没有遇到您的“相等”对象进行比较。注意,TreeSet不是像 List 或 Array 这样的普通顺序遍历,而是树遍历。

要解决这个问题,你需要确保你的 compareTo(Var var) 方法遵循 Object 的 equals 契约

更好的代码是:-

           @Override
            public int compareTo(Var var) {
                    if (var == null)
                            throw new NullPointerException("Object is null");
                    return this.getKey().compareTo(var.getKey()) ;
            }

这应该可以解决你所有的问题

【讨论】:

  • hyym,我实际上使用了 bobbel 的想法,但我也尝试了这个,并且:我仍然在 Set 中看到 8 个元素,所以很好......但这不是从 set 中“更新”值。新的“Var”必须替换旧的。但是还是谢谢,我记得“规则”也许我会在其他代码中需要它:>
【解决方案2】:

compareTo 用于评估大于/小于/等于。

Set 的相等性是通过覆盖Object#equals(Object) 方法来确定的。 每当您实现 equals() 时,您还应该实现 hashCode() 方法。

【讨论】:

  • 我也使用 equals 但是...当我添加调试时,我没有看到来自 equals 方法的任何调试消息
猜你喜欢
  • 1970-01-01
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
  • 2021-03-09
  • 1970-01-01
  • 2020-02-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多