【问题标题】:Java HashSet with a custom equality criteria? [duplicate]具有自定义相等标准的Java HashSet? [复制]
【发布时间】:2013-01-30 14:05:03
【问题描述】:

我一直在寻找类似于 Java TreeSet 在实例化时接收自定义比较器的能力,因此我不需要使用对象的默认相等(和哈希码)标准。

我能想出的最接近的方法是将我的对象包装在一个私有自定义类中,但这似乎很老套 :( 这最终成为编程时反复出现的主题,所以我想知道是否已经有一些东西可供我们使用使用。也许在公共库中?

谢谢

【问题讨论】:

  • 标题里写的是HashSet,正文里写的是TreeSet?你现在想要什么?
  • 如果它经常出现,那么也许您可以自己滚动? Guava 必须担心开发人员滥用 API,而您不必担心有限的使用。
  • 肯定是java中反复出现的主题...

标签: java set hashset


【解决方案1】:

不,您已经找到了您应该使用的确切解决方案。

即使对于TreeSetfrowned upon 使用与equals 不兼容的比较标准:

请注意,如果有序集合要正确实现 Set 接口,有序集合维护的顺序(无论是否提供显式比较器)必须与 equals 一致。

我不了解 Apache Commons,但 Guava specifically rejected 请求这类事情,虽然你可以使用 Guava Equivalence 实现你想要的:

Equivalence<T> equivalence = new Equivalence<T>() {
    @Override
    protected boolean doEquivalent(T a, T b) {
        return CustomComparator.equals(a, b);
    }

    @Override
    protected int doHash(T item) {
        return CustomHashCodeGenerator.hashCode(item);
    }
};
List<T> items = getItems();
Set<Equivalence.Wrapper<T>> setWithWrappedObjects = items.stream()
    .map(item -> equivalence.wrap(item))
    .collect(Collectors.toSet());

【讨论】:

  • “我不了解 Apache Commons,但 Guava 明确拒绝了此类请求”。有趣
【解决方案2】:

你是对的,当你想使用任何TreesTreeMapTreeSet)时,你添加的对象必须实现Comparable

对于原始类型,Java 已经为您解决了这个问题。
对于自定义对象,您有 3 种可能性:

  1. 您的一个对象已经有一个原始类型的唯一 id 或已经实现 compareTo() 的类型(如 String) 然后将此字段用于 compareTo,如果其他值对于相等性不重要。 (但是equals()也必须只使用这一字段)

  2. 使用来自 Apache 的 EqualsBuilder: 这适用于反射,并不是最快的解决方案

  3. 自己写,阅读一些教程如何做到这一点:例如:

乔什·布洛赫:有效的 Java 第 2 版

但是不要忘记equals()compareTo() 必须兼容(以及hashCode()),这样你就不会违反equals 合约。 (合同本身不太容易理解,但如果你拒绝其中一个等于教程,就会清楚。)

或者忘记这一切,使用HashSetHashMap

【讨论】:

    【解决方案3】:

    有几个第三方集合框架允许自定义相等逻辑。这非常适合覆盖无法更改源的对象的相等性。

    Trove 的地图/集合支持使用自定义散列策略, 允许您根据输入的特征调整集合 数据。此功能还允许您在需要时定义散列函数 覆盖 Object.hashCode() 是不可行的。

    要实现这一点,任何需要标准校正的类型都必须 实现 HE-Collection 接口 EqualsAndHashCorrection。这 接口定义了方法 hashCodeInHeCollection() 和 equalsInHeCollection(Object),作为修正 错误实现的方法 hashCode() 和 equals(Object)。

    【讨论】:

      猜你喜欢
      • 2016-03-19
      • 2016-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-13
      • 1970-01-01
      • 2013-04-28
      • 2011-11-05
      相关资源
      最近更新 更多