我需要知道两个对象的参数值相同。
我不知道对象的类型。 它们的参数值相同,但可能有不同的引用。
像:
Person person = new Person("Alfred", "00001" ...);
Person person2 = new Person("Alfred", "00001" ...);
list.add(person, person2);
记得我不知道对象的类型,我不能修改对象。 可能是人,动物......或者其他不同的东西。
我需要知道当我迭代列表时,它是否有重复的对象。
for (Object item : list) {
}
泰
答案 0 :(得分:1)
在Java 8中(需要覆盖hashCode()
& equals(Object obj)
方法):
cat c1=new cat("lolo", "black");
cat c3=new cat("lolo", "black");
List<Object> arrayList = new ArrayList<Object>();
arrayList.add(c1);
arrayList.add(c3);
List<Object> deduped = arrayList.stream().distinct().collect(Collectors.toList());
旧Java版本:
如果您想要消除重复的对象,请使用HashSet
并且必须实现(覆盖)hashCode()
方法:
public class cat {
String name;
String color;
public cat(String name, String color) {
super();
this.name = name;
this.color = color;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((color == null) ? 0 : color.hashCode());
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;
cat other = (cat) obj;
if (color == null) {
if (other.color != null)
return false;
} else if (!color.equals(other.color))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public static void main(String[] args) {
cat c1=new cat("lolo", "black");
cat c2=new cat("lolo2", "white");
cat c3=new cat("lolo", "black");
List<Object> arrayList = new ArrayList<Object>();
arrayList.add(c1);
arrayList.add(c3);
Set<Object> uniqueElements = new HashSet<Object>(arrayList);
arrayList.clear();
arrayList.addAll(uniqueElements);
System.out.println(arrayList.size());//will be 1
}
}
如果您需要了解如何做出更多信息hashcode()
,请阅读以下答案:Best implementation for hashCode method
如果所有对象类都实现(覆盖)equal()
方法,则可以使用它。
示例:
public class cat {
String name;
String color;
public cat(String name, String color) {
super();
this.name = name;
this.color = color;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
cat other = (cat) obj;
if (color == null) {
if (other.color != null)
return false;
} else if (!color.equals(other.color))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public static void main(String[] args) {
cat c1=new cat("lolo", "black");
cat c2=new cat("lolo2", "white");
cat c3=new cat("lolo", "black");
Object o1=c1;
Object o2=c2;
Object o3=c3;
System.out.println(o1.equals(o2));//false
System.out.println(o1.equals(o3));//true
}
}
答案 1 :(得分:1)
可能性1:equals()
在最简单的情况下,equals()
已在要比较的对象的类中实现,以便比较内部状态。在这种情况下,您只需致电a.equals(b)
(假设a
不是null
)并将其称为一天。
可能性2:使用反思
如果你不能认为equals()
已经以适合你的方式实施,那就变得有点困难了。您应该查找提供deepEquals()
操作的库,这些库将使用反射来查看引擎并比较实际的类,如果等于两个对象中的字段。
我建议使用Apache Commons Lang提供的EqualsBuilder
类,因为我发现它工作得很好。
请注意,据我记得,自Java 7以来存在的Objects.deepEquals()
实际上并没有根据其文档执行深度比较,因为它将工作委托给第一个参数的equals()
方法
当然,如果您有时间并且知道或想要学习Reflection API,您也可以自己实施deepEquals()
操作。
答案 2 :(得分:1)
我看到有两种方式,使用equals()
方法的首选Java方式,以及基于反射的脆弱方式。
使用equals()
所有体面的Java类都应该实现equals()
方法,用于比较两个对象在语义上具有相同的内容。我想这个定义符合你的要求&#34;他们的参数中的相同值&#34; (它不是你要求的字面意思,但有充分理由 - 见下文)。当然,这依赖于具有适当equals()实现的相关类,或者您可以将一个添加到相关类。如果可能,就这样走。
使用反射
免责声明:如果可能,请尽量避免使用。
Java允许您查找给定类具有的字段,并读取给定实例的此类字段的值。所以你可以:
为什么特定于类的equals()方法优于盲区值比较
并非所有字段都是相同的。通常,类具有内部字段,这些字段与您在要求属性等效时要比较的对象属性无关。例子:
lastAccess
日期。从技术上讲,您在大多数时间会得到不同的值,但这并不意味着某些相关的对象属性不同。盲目地比较对象字段总是会陷入比较这些字段的陷阱,尽管它们没有你期望的语义含义。
只有类本身知道哪些字段可以有效地比较,哪些不是。这就是为什么每个类都应该有自己的equals()
方法,以及为什么应该用它来进行内容比较。
答案 3 :(得分:0)
只需为列表中的每个类实施适当的equals
和hashCode
方法。
然后将列表转换为集合并比较这两个集合的大小,您将知道重复项是否在该列表中。
Set set = new HashSet(list);
if(set.size() == list.size()) {
System.out.println("No duplicates.");
} else {
System.out.println("Found duplicates.");
}