我希望根据Set
/ equals
对同一种对象的不同实现,有两个hashCode
个集合包含唯一对象。
例如,一个Set
仅适用于具有不同时间戳的元素,而equals
应返回a.timestamp!=b.timestamp
,但另一个集合可能仅适用于具有不同的元素名称等于a.name!=b.name
。
有没有一种微不足道的方法来实现这一目标?如何为每个不同的Set
制作自定义等号?
答案 0 :(得分:1)
您的建议听起来像滥用equals
方法和Set
界面。
您的用例定义了两个类别,通过这两个类别可以对给定类型的对象进行分组(时间戳和名称),并且您希望有两个集合,每个集合最多为每个类别保留一个实例。
要做到这一点,拥有帮助器集会更有意义:
Set<String> timestamps;
Set<String> names;
然后,您可以为这些集添加名称和时间戳,并使用它们来检查是否应将对象添加到目标集合(不必是集合)。
例如:
List<SomeClass> timestampCategories = new ArrayList<SomeClass>();
List<SomeClass> nameCategories = new ArrayList<SomeClass>();
for (SomeClass object : inputCollection) {
if (!timestamps.contains(object.getTimestamp()) {
timestamps.add(object.getTimestamp());
timestampCategories.add(object);
}
if (!names.contains(object.getName()) {
names.add(object.getName());
nameCategories.add(object);
}
}
答案 1 :(得分:1)
创建两个包装值类,并将equals
和hashCode
实现放在那里。
public class Test {
Set<NameBeanWrapper> names = new HashSet<Test.NameBeanWrapper>();
Set<TimestampBeanWrapper> timestamps = new HashSet<Test.TimestampBeanWrapper>();
public void store(Set<Bean> initial) {
for (Bean bean : initial) {
names.add(new NameBeanWrapper(bean));
timestamps.add(new TimestampBeanWrapper(bean));
}
}
public static class Bean {
String name;
Long timestamp;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
}
public static class NameBeanWrapper {
final Bean bean;
public NameBeanWrapper(Bean bean) {
this.bean = bean;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((bean == null || bean.name == null) ? 0 : bean.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;
}
NameBeanWrapper other = (NameBeanWrapper) obj;
if (bean == null) {
if (other.bean != null) {
return false;
}
}else if (bean.name == null) {
if (other.bean.name != null) {
return false;
}
} else if (!bean.name.equals(other.bean.name)) {
return false;
}
return true;
}
}
public static class TimestampBeanWrapper {
final Bean bean;
public TimestampBeanWrapper(Bean bean) {
this.bean = bean;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((bean == null || bean.timestamp == null) ? 0 : bean.timestamp.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;
}
NameBeanWrapper other = (NameBeanWrapper) obj;
if (bean == null) {
if (other.bean != null) {
return false;
}
}else if (bean.timestamp == null) {
if (other.bean.timestamp != null) {
return false;
}
} else if (!bean.timestamp.equals(other.bean.timestamp)) {
return false;
}
return true;
}
}
}
答案 2 :(得分:0)
正如所建议:
你想拥有同一个对象的两个列表吗?为什么不用你需要的所有属性创建一个父object
然后实现两个对象,而不是从第一个继承不同的equals和hash?
答案 3 :(得分:0)
好的,我想知道是否有一种简单的方法可以指定要在Set中使用的equals / hashcode。我看到没有人听说过这样的事情。
如果无法做到这一点,我总是可以使用自定义哈希码作为键的Map,然后当我需要获取Collection时,我得到Map.values()。我想避免这种情况,因为要保持较低的内存使用率,但也许就是这样......