我在对一个对象列表使用Java8中distinct()进行去重时发现,结果List中的对象并未去重。
于是我点进了distinct()的源码。
先来一步一步看看源码
//这是那个distinct的接口
Stream<T> distinct();
//这是distinct接口的实现类
@Override
public final Stream<P_OUT> distinct() {
return DistinctOps.makeRef(this);
}
//再点进去看看
static <T> ReferencePipeline<T, T> makeRef(AbstractPipeline<?, T, ?> upstream) {
//太多就省略了
//看一行关键的代码
if (lastSeen == null || !t.equals(lastSeen))
}
//原来distinct()底层调用了equals()方法去做比较
//那为什么equals()方法没有比较出重复的对象呢
//点开equals()的源码我们会发现
public boolean equals(Object obj) {
return (this == obj);
}
//这里用了 == 去做比较(==比较两个对象在内存中的地址是否相同)
//这下原因就清楚了,那我们就直接给出解决方案
//重写类中的equals()方法 这里需要注意,重写equals()必须重写hashcode()
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PledgorToPawnee that = (PledgorToPawnee) o;
return huid == that.huid &&
Objects.equals(relUnique, that.relUnique) &&
Objects.equals(startHcode, that.startHcode) &&
Objects.equals(startName, that.startName) &&
Objects.equals(endHcode, that.endHcode) &&
Objects.equals(endName, that.endName) &&that.pledgorToPawneeDetailList) &&
Objects.equals(relTypeName, that.relTypeName);
}
//搞定收工
重写equals()方法时,我们可以根据自己的需求,哪些属性相同时定义为这两个对象相同,来自行修改equals()的实现。
另外还有一点也说明一下:
List<对象> 在调用contains()方法时,也是通过底层调用超类Object的equals的方法实现的
再补充一个点:
重写equals()方法时,方法的实现中通过Objects.equals()方法去比较属性的值
看一下Objects.equals()的源码:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
看到这里有人可能有疑问了,如果 a、b 都为null会报错吗?
哈哈哈,答案是不会的,因为:
System.out.println(null == null);//true
问题解决!!!