以下是这种情况:我想基于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_a
和id_b
是相同的,而对象C是不同的。
要在代码中确定这一点,我打算将ID转换为字符串,并将它们与中间的分隔符char连接在一起(例如"{id_a},{id_b}"
),然后将它们添加到{{1测试唯一性。
我的问题是,有更好的方法吗?(更好的是,我的意思是更有效率和/或更少kludgy)
答案 0 :(得分:2)
如果您想使用HashSet
,可以覆盖hashCode
和equals
,专门查看这两位成员。
哈希代码:(31
只是Java中用于散列的一个主要版本)
return 31*id_a + id_b;
等于:(您显然需要添加instanceof
支票并输入转化次数)
return id_a == other.id_a && id_b == other.id_b;
如果您不想将这些函数绑定到类,因为它在其他地方使用的方式不同,但您仍想使用HashSet
,则可以考虑:
创建一个存储在集合中的中间类,它将您的类作为成员包含,并适当地实现上述方法。
使用字符串方法
使用HashSet<Point>
- Point
不适合非协调用途,因为成员只需命名为x
和y
,但我觉得它很有用有这样一个类,至少对于非生产代码。
或者,如果您想使用TreeSet
,您可以让您的班级实施Comparable
(覆盖compareTo
)或为Comparator
提供TreeSet
,两者都主要在一个id上进行比较,其次在另一个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);
答案 1 :(得分:2)
不确定这是否更高效或更少kludgy。你可以使用主id(根据你的注释)保留原始的hashcode / equals,然后创建一个包含复合ida,idb的hashcode / equals的包装器。也许你需要的东西超过顶部。
CompositeIdEntity.java
public interface CompositeIdEntity {
long getIdA();
long getIdB();
}
Entity.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;
}
}
Test.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]
答案 2 :(得分:1)
看到这一点,在这里我重写了equals()和hashcode()以确保&#34; name&#34;的唯一性。 Person对象的字段
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;
}
}