0

情况如下:我想根据 2 个不同的 ID 测试 2 个对象的唯一性。例子:

// Note I'm using JSON notation to keep things simple; the actual code 
// is with Java Objects

// OBJECT A
{
    main_id: 0,
    id_a: 123,
    id_b: 456
}

// OBJECT B
{
    main_id: 1,
    id_a: 123,
    id_b: 456
}

// OBJECT C
{
    main_id: 2,
    id_a: 123,
    id_b: 789
}

在示例中,对象 A 和 B 相同,因为id_aid_b相同,而对象 C 不同。

为了在代码中确定这一点,我计划将两个 ID 都转换为字符串,并将它们与中间的分隔符字符(例如,"{id_a},{id_b}")连接在一起,然后将它们添加到 aSet<String>以测试唯一性。

我的问题是,有没有更好的方法?(更好,我的意思是更高效和/或更少笨拙

4

3 回答 3

2

如果您想使用HashSet,您可以覆盖hashCodeequals专门查看这两个成员。

哈希码:(31只是 Java 中普遍用于哈希的素数)

return 31*id_a + id_b;

等于:(您显然需要添加instanceof检查和类型转换)

return id_a == other.id_a && id_b == other.id_b;

如果您不想将这些函数绑定到该类,因为它在其他地方的使用方式不同,但您仍想使用HashSet,您可以考虑:

  • 创建要存储在集合中的中间类,它将包含您的类作为成员并适当地实现上述方法。

  • 使用你的字符串方法

  • 使用HashSet<Point>-Point不适用于非协调目的,因为成员只是命名为xand y,但我确实发现有这样一个可用的类很有用,至少对于非生产代码。


或者,如果你想使用TreeSet,你可以让你的类实现Comparable(覆盖compareTo)或为 提供一个ComparatorTreeSet这两者都将主要在一个 id 上进行比较,然后在另一个上进行比较。

基本思想看起来像这样:

if (objectA.id_a != objectB.id_a)
  return Integer.compare(objectA.id_a, objectB.id_a);
return Integer.compare(objectA.id_b, objectB.id_b);
于 2014-04-29T21:03:57.893 回答
2

不确定这是否更有效或更不那么笨拙。您可以使用主 ID(根据您的评论)保留原始哈希码/等于,然后为复合 ida idb 创建一个包含哈希码/等于的包装器。不过,也许超出了您的需求。

CompositeIdEntity.java

public interface CompositeIdEntity {

    long getIdA();

    long getIdB();

}

实体.java

public class Entity implements CompositeIdEntity {

    private final long mainId;

    private final long idA;

    private final long idB;

    public Entity(long mainId, long idA, long idB) {
        this.mainId = mainId;
        this.idA = idA;
        this.idB = idB;
    }

    @Override
    public long getIdA() {
        return idA;
    }

    @Override
    public long getIdB() {
        return idB;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + (int) (mainId ^ (mainId >>> 32));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Entity other = (Entity) obj;
        if (mainId != other.mainId)
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Entity [mainId=" + mainId + ", idA=" + idA + ", idB=" + idB
                + "]";
    }

}

CompositeIdWrapper.java

public class CompositeIdWrapper {

    private final CompositeIdEntity compositeIdEntity;

    public CompositeIdWrapper(CompositeIdEntity compositeIdEntity) {
        this.compositeIdEntity = compositeIdEntity;
    }

    public CompositeIdEntity getCompositeIdEntity() {
        return compositeIdEntity;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + (int) (compositeIdEntity.getIdA() ^ (compositeIdEntity
                        .getIdA() >>> 32));
        result = prime * result
                + (int) (compositeIdEntity.getIdB() ^ (compositeIdEntity
                        .getIdB() >>> 32));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        CompositeIdWrapper other = (CompositeIdWrapper) obj;
        if (compositeIdEntity.getIdA() != other.compositeIdEntity.getIdA())
            return false;
        if (compositeIdEntity.getIdB() != other.compositeIdEntity.getIdB())
            return false;
        return true;
    }

}

测试.java

import java.util.HashSet;
import java.util.Set;

public class Test {

    public static void main(String[] args) {
        Entity en1 = new Entity(0, 123, 456);
        Entity en2 = new Entity(1, 123, 456);
        Entity en3 = new Entity(2, 123, 789);
        Entity en4 = new Entity(2, 123, 456);
        Entity en5 = new Entity(1, 123, 789);

        // Set based on main id
        Set<Entity> mainIdSet = new HashSet<>();
        mainIdSet.add(en1);
        mainIdSet.add(en2);
        mainIdSet.add(en3);
        mainIdSet.add(en4);
        mainIdSet.add(en5);

        System.out.println("Main id set:");
        for (Entity entity : mainIdSet) {
            System.out.println(entity);
        }

        // Set based on ida, idb
        Set<CompositeIdWrapper> compositeIdSet = new HashSet<>();
        compositeIdSet.add(new CompositeIdWrapper(en1));
        compositeIdSet.add(new CompositeIdWrapper(en2));
        compositeIdSet.add(new CompositeIdWrapper(en3));
        compositeIdSet.add(new CompositeIdWrapper(en4));
        compositeIdSet.add(new CompositeIdWrapper(en5));

        System.out.println("Composite id set:");
        for (CompositeIdWrapper wrapped : compositeIdSet) {
            System.out.println(wrapped.getCompositeIdEntity());
        }

    }

}

输出

Main id set:
Entity [mainId=1, idA=123, idB=456]
Entity [mainId=2, idA=123, idB=789]
Entity [mainId=0, idA=123, idB=456]
Composite id set:
Entity [mainId=0, idA=123, idB=456]
Entity [mainId=2, idA=123, idB=789]
于 2014-04-29T21:58:15.283 回答
1

看到这个,这里我覆盖了 equals() 和 hashcode() 以确保 Person 对象的“name”字段的唯一性

public class SetObjectEquals {
    Person p1 = new Person("harley");
    Person p2 = new Person("harley");

    public void method1() {
        Set<Person> set = new HashSet<Person>();
        set.add(p1);
        set.add(p2);
        System.out.println(set);
    }

    public static void main(String[] args) {
        SetObjectEquals obj = new SetObjectEquals();
        obj.method1();
    }

}

class Person {
    String name;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

    Person(String name) {
        this.name = name;
    }
}
于 2014-04-29T20:58:36.283 回答