【问题标题】:Why can't custom comparator be used with hashSet to check duplicate objects为什么不能将自定义比较器与 hashSet 一起使用来检查重复对象
【发布时间】:2014-02-17 05:09:09
【问题描述】:

我想使用自定义比较器过滤来自HashSet 的重复对象。

Mobile 类中,我定义了一个非静态嵌套Comparator 类用于比较。此比较器使用的标准是Mobile 对象的id 字段。

Set<Mobile> treeSet = new TreeSet<>(new Mobile().new Comparator()); // works


Set<Mobile> hashSet = new HashSet<>(new Mobile().new Comparator()); // does not work

尽管它对TreeSet 非常有效,但当我使用HashSet 尝试此操作时,Eclipse 会显示语法错误,

如果我想使用HashSet,我似乎需要覆盖Mobile 类中的equalshashcode 方法。不过,我更喜欢使用比较器。

为什么会这样?

【问题讨论】:

  • 请解释我......如果你能帮助我回答我的问题或者我的意思是如果我想将 list 转换为 hashset ,使用自定义重复标准,最好的方法是什么......
  • 我不明白你想做什么,你想在集合中存储Mobile对象还是Comperator对象?如果是第一个,在Mobile 类中实现hashcodeequals(您可以将Comperator 实现用于equals)。 HashSet 没有接受 Comperator 作为第一个参数的构造函数,这也没有任何意义。 TreeSet 确实如此,因为它使用比较器对对象进行排序(但 HashSet 是无序的)
  • 这里是 java api:docs.oracle.com/javase/7/docs/apiComparator 是一个接口,不能仅通过 new 调用来实例化(必须定义必要的函数)。
  • @Teepeemm ComparatorMobile 类的内部类的名称。
  • @MarkoTopolnik Mobile 有一些文档吗?它不在JDK中,搜索“Java Mobile api”并没有给出api(不是我能识别的)。

标签: java eclipse hashset


【解决方案1】:
HashSet<Mobile> mobileSet = new HashSet(new Mobile().new Comparator())

让我们列举一下这行代码有哪些问题:

  • 缺少结束分号(您的“语法错误”);
  • new HashSet 上缺少泛型类型参数(或菱形运算符);
  • 它正在使用与HashSet(Collection&lt;? extends E&gt; coll) 不兼容类型的构造函数参数。

HashSet 的 Javadoc 解释了哈希集的工作原理。应该很容易意识到它与Comparators 无关。

【讨论】:

  • 在语法上这个答案是正确的,但仍然不能解决问题。假设如果 SET 在某种程度上具有 GET 方法,则可以通过执行第一次 get 操作然后检查不可能的额外条件来解决此问题。另一种尝试是将 List 中的元素进一步存储到具有公共 ID 的映射中,同时添加新元素检查额外条件并仅在满足所有条件时在 Map 中添加元素。
  • 不幸的是,这个答案被接受了,虽然它甚至没有说明 TreeSet 对那个比较器做了什么(这可能是混淆问题的根本原因) .在我看来,这使这个问题成为一个未回答的问题,并且错误地接受了答案,该答案已过早关闭。
  • @bvdb 您愿意编辑和改进答案吗?这是一个糟糕的答案,但遗憾的是无法删除已接受的答案。
【解决方案2】:

Hashset 旨在不接受重复!因此,如果您的集合不包含给定元素,它会将其添加到集合中。但是,如果在您的集合中出现这样的元素,则不会添加第二个(相同)元素并将被丢弃。

哈希集:

类为基本操作(添加, 删除、包含和调整大小)。它不保证
的顺序 元素将随着时间的推移保持不变迭代性能取决于 HashSet的初始容量和负载因子。这是
接受默认负载系数非常安全,但您可能需要指定
初始容量大约是您预期大小的两倍
集增长。

树集:

保证基本操作的 log(n) 时间成本(添加、删除和 contains) 保证 set 的元素将被排序(升序, 自然的,或者你通过它的构造函数指定的那个)不 为迭代性能提供任何调整参数 处理有序集合的便捷方法,如 first()、last()、 headSet() 和 tailSet() 等

要点:

两者都保证元素的无重复集合一般是 更快地将元素添加到 HashSet,然后转换集合 到 TreeSet 以进行无重复的排序遍历。都不是 实现是同步的。也就是说,如果多个线程访问一个 同时设置,并且至少有一个线程修改了该集合,它 必须在外部同步。 LinkedHashSet 在某种意义上是 介于 HashSet 和 TreeSet 之间。实现为哈希表 有一个链表贯穿它,但是它提供 插入排序迭代与排序遍历不同 由 TreeSet 保证。

【讨论】:

    猜你喜欢
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多