首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在java中,除了实现自定义的equals()和hashCode()之外,还可以做一些类似于比较的东西吗?

在java中,除了实现自定义的equals()和hashCode()之外,还可以做一些类似于比较的东西吗?
EN

Stack Overflow用户
提问于 2011-03-05 21:27:25
回答 7查看 20.8K关注 0票数 61

我有一个对象数组,我想将它与另一个对象数组连接起来,除了具有相同id的对象。这些对象在系统中的许多地方使用,并且没有实现散列代码或equals。所以我不想实现hashCode()equals(),因为我害怕破坏系统中使用这些对象的某个地方,我不知道这一点。

我希望将所有这些对象放在一个集合中,但又以某种方式使这些对象使用自定义的hashCode()equals()。有点像自定义的Comparator,但是等同的。

EN

回答 7

Stack Overflow用户

发布于 2011-03-07 00:17:42

90%的情况下,当用户想要一个等价关系时,已经有了一个更直接的解决方案。您想仅根据ids对一堆东西进行重复数据删除吗?您是否可以将它们全部放入一个映射中,并将ids作为键,然后获取该ids的values()集合?

票数 15
EN

Stack Overflow用户

发布于 2014-06-23 23:57:05

HashingStrategy是您正在寻找的概念。它是一个策略接口,允许您定义equals和hashcode的自定义实现。

代码语言:javascript
复制
public interface HashingStrategy<E>
{
    int computeHashCode(E object);
    boolean equals(E object1, E object2);
}

正如其他人所指出的,您不能将HashingStrategy与内置的HashSetHashMap一起使用。Eclipse Collections包括一个名为UnifiedSetWithHashingStrategy的集合和一个名为UnifiedMapWithHashingStrategy的映射。

让我们看一个例子。下面是一个可以在UnifiedSetWithHashingStrategy中使用的简单Data类。

代码语言:javascript
复制
public class Data
{
    private final int id;

    public Data(int id)
    {
        this.id = id;
    }

    public int getId()
    {
        return id;
    }

    // No equals or hashcode
}

下面是如何设置和使用UnifiedSetWithHashingStrategy的方法。

代码语言:javascript
复制
java.util.Set<Data> set =
  new UnifiedSetWithHashingStrategy<>(HashingStrategies.fromFunction(Data::getId));
Assert.assertTrue(set.add(new Data(1)));

// contains returns true even without hashcode and equals
Assert.assertTrue(set.contains(new Data(1)));

// Second call to add() doesn't do anything and returns false
Assert.assertFalse(set.add(new Data(1)));

为什么不直接使用Map呢?UnifiedSetWithHashingStrategy的内存只有UnifiedMap的一半,HashMap的四分之一。有时你没有一个方便的键,必须创建一个合成的键,比如元组。这会浪费更多的内存。

我们如何执行查找?请记住,Set有contains(),但没有get()。除了MutableSet之外,UnifiedSetWithHashingStrategy还实现了Pool,因此它还实现了一种形式的get()

注意:我是Eclipse Collections的提交者。

票数 11
EN

Stack Overflow用户

发布于 2011-03-05 22:17:01

当然,您可以创建一些外部对象,提供相等比较和HashCode。但是Java的内置集合不会使用这样的对象进行比较/查找。

我曾经在我的package-collection (刚刚翻译成英语)中创建了一个这样的接口:

代码语言:javascript
复制
public interface HashableEquivalenceRelation {

    /**
     * Returns true if two objects are considered equal.
     *
     * This should form an equivalence relation, meaning it
     * should fulfill these properties:
     *  <ul>
     *    <li>Reflexivity:  {@code areEqual(o, o)}
     *            should always return true.</li>
     *    <li>Symmetry: {@code areEqual(o1,o2) == areEqual(o2,o1)}
     *            for all objects o1 and o2</li>
     *    <li>Transitivity: If {@code areEqual(o1, o2)} and {@code areEqual(o2,o3)},
     *            then {@code areEqual(o1,o3}} should hold too.</li>
     *  </ul>
     * Additionally, the relation should be temporary consistent, i.e. the
     * result of this method for the same two objects should not change as
     * long as the objects do not change significantly (the precise meaning of
     * <em>change significantly</em> is dependent on the implementation).
     *
     * Also, if {@code areEqual(o1, o2)} holds true, then {@code hashCode(o1) == hashCode(o2)}
     * must be true too.
     */
    public boolean areEqual(Object o1, Object o2);

    /**
     * Returns a hashCode for an arbitrary object.
     *
     * This should be temporary consistent, i.e. the result for the same
     * objects should not change as long as the object does not change significantly
     * (with change significantly having the same meaning as for {@link areEqual}).
     *
     * Also, if {@code areEqual(o1, o2)} holds true, then {@code hashCode(o1) == hashCode(o2)}
     * must be true too.
     */
    public int hashCode(Object o);

}

然后我有了一组接口CustomCollectionCustomSetCustomListCustomMap,等等,就像java.util中的接口一样,但是对所有的方法都使用了这样的等价关系,而不是Object.equals给出的内置关系。我也有一些默认的实现:

代码语言:javascript
复制
/**
 * The equivalence relation induced by Object#equals.
 */
public final static EquivalenceRelation DEFAULT =
    new EquivalenceRelation() {
        public boolean areEqual(Object o1, Object o2)
        {
            return
                o1 == o2 ||
                o1 != null &&
                o1.equals(o2);
        }
        public int hashCode(Object ob)
        {
            return
                ob == null?
                0 :
                ob.hashCode();
        }
        public String toString() { return "<DEFAULT>"; }
    };

/**
 * The equivalence relation induced by {@code ==}.
 * (The hashCode used is {@link System#identityHashCode}.)
 */
public final static EquivalenceRelation IDENTITY =
    new EquivalenceRelation() {
        public boolean areEqual(Object o1, Object o2) { return o1 == o2; }
        public int hashCode(Object ob) { return System.identityHashCode(ob); }
        public String toString() { return "<IDENTITY>"; }
    };

/**
 * The all-relation: every object is equivalent to every other one.
 */
public final static EquivalenceRelation ALL =
    new EquivalenceRelation() {
        public boolean areEqual(Object o1, Object o2) { return true; }
        public int hashCode(Object ob) { return 0; }
        public String toString() { return "<ALL>"; }
    };

/**
 * An equivalence relation partitioning the references
 * in two groups: the null reference and any other reference.
 */
public final static EquivalenceRelation NULL_OR_NOT_NULL =
    new EquivalenceRelation() {
        public boolean areEqual(Object o1, Object o2)
        {
            return (o1 == null && o2 == null) ||
                (o1 != null && o2 != null);
        }
        public int hashCode(Object o) { return o == null ? 0 : 1; }
        public String toString() { return "<NULL_OR_NOT_NULL>"; }
    };

/**
 * Two objects are equivalent if they are of the same (actual) class.
 */
public final static EquivalenceRelation SAME_CLASS =
    new EquivalenceRelation() {
        public boolean areEqual(Object o1, Object o2)
        {
            return o1 == o2 || o1 != null && o2 != null &&
                o1.getClass() == o2.getClass();
        }
        public int hashCode(Object o) { return o == null ? 0 : o.getClass().hashCode(); }
        public String toString() { return "<SAME_CLASS>"; }
    };


/**
 * Compares strings ignoring case.
 * Other objects give a {@link ClassCastException}.
 */
public final static EquivalenceRelation STRINGS_IGNORE_CASE =
    new EquivalenceRelation() {
        public boolean areEqual(Object o1, Object o2)
        {
            return o1 == null ?
                o2 == null :
                ((String)o1).equalsIgnoreCase((String)o2);
        }
        public int hashCode(Object o)
        {
            return o == null ? -12345 : ((String)o).toUpperCase().hashCode();
        }
        public String toString() { return "<STRINGS_IGNORE_CASE>"; }
    };


/**
 * Compares {@link CharSequence} implementations by content.
 * Other object give a {@link ClassCastException}.
 */
public final static EquivalenceRelation CHAR_SEQUENCE_CONTENT =
    new EquivalenceRelation() {
        public boolean areEqual(Object o1, Object o2) 
        {
            CharSequence seq1 = (CharSequence)o1;
            CharSequence seq2 = (CharSequence)o2;
            if (seq1 == null ^ seq2 == null) // nur eins von beiden null
                return false;
            if (seq1 == seq2)   // umfasst auch den Fall null == null
                return true;
            int size = seq1.length();
            if (seq2.length() != size)
                return false;
            for (int i = 0; i < size; i++)
                {
                    if (seq1.charAt(i) != seq2.charAt(i))
                        return false;
                }
            return true;
        }
        /**
         * Entrspricht String.hashCode
         */
        public int hashCode(Object o)
        {
            CharSequence sequence = (CharSequence)o;
            if (sequence == null)
                return 0;
            int hash = 0;
            int size = sequence.length();
            for (int i = 0; i < size; i++)
                {
                    hash = hash * 31 + sequence.charAt(i);
                }
            return hash;
        }
    };
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5204082

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档