1.我们大家都知道,set集合的特点就是没有重复的元素。如果集合中的数据类型是基本数据类型,可以直接将list集合转换成set,就会自动去除重复的元素,这个就相对比较简单。
public class Test {
public static void main(String[] args) {
List list = new ArrayList();
list.add(11);
list.add(12);
list.add(13);
list.add(14);
list.add(15);
list.add(11);
System.out.println(list);
Set set = new HashSet();
List newList = new ArrayList();
set.addAll(list);
newList.addAll(set);
System.out.println(newList);
}
}
输出结果为:
2.但是当list集合中存储的类型是对象类型的时候,而我们又想把对象中某一个或多个属性值相同的对象进行去重,那么这种方式就不行了
3.我们要怎么做呢,我们如果还想用set方法去重那么就可以重写list对象中的hashCode和equals方法来实现list转化为Set时相同属性值的对象去重
4.例如:我们想对活动商品ActivityItem对象中,商品skuCode相同(销售单元无所谓)的对象去重复,那么就可以重写ActivityItem对象的hashCode和equals方法来实现
@Override
public int hashCode() {
/**
* 首先判断该对象的hashCode值是否相同
* 如果相同则再进一步equals方法比较是否相同,如果equals方法也相同则可以认为是同意对象
* 如果hashCode不相同则肯定不是同一个对象,那么就没必要比较equals了
* 所以我们可以利用重新对象的hashCode和equals方法来实现对自定义的对象去重
*
* 这也同样证明了一点:两个对象equals相等,则它们的hashcode必须相等,反之则不一定。
* 两个对象相等那么他们的hashCode和equals一定相等,但如果只有hashcode那么两个对象不一定相等
*/
return Objects.hash(super.hashCode(), skuCode);
}
public static void main(String[] args) {
List<ActivityItem> items = new ArrayList<>();
ActivityItem item1 = new ActivityItem();
item1.setSkuCode("111");
item1.setUnitCode("a");
ActivityItem item2 = new ActivityItem();
item2.setSkuCode("222");
item2.setUnitCode("b");
ActivityItem item3 = new ActivityItem();
item3.setSkuCode("111");
item3.setUnitCode("c");
items.add(item1);
items.add(item2);
items.add(item3);
System.out.println("list:"+items.toString());
Set<ActivityItem> hashSet = new HashSet<>();
hashSet.addAll(items);
items.clear();
items.addAll(hashSet);
System.out.println("list22:"+items.toString());
}
输出结果:
list:[ActivityItem(skuCode=111, unitCode=a), ActivityItem(skuCode=222, unitCode=b), ActivityItem(skuCode=111 unitCode=c, unitName=null)]
list222:[ActivityItem(skuCode=111, unitCode=a), ActivityItem(skuCode=222, unitCode=b))]
5.下面来说明这样做为什么可以对对象元素进行去重
HashSet的add()
方法,首先会使用当前集合中的每一个元素和新添加的元素进行hash值比较
如果hash值不一样,那么肯定不是相同的对象,则直接添加新的元素;
如果hash值一样,那么就比较地址值或者使用equals方法进行比较
而按照我们上述例子中重写的方法来看,我们期望的是想要把对象中skuCode相同的元素做相同对象进行去重,所以我们要使用了Objects.hash(super.hashCode(), skuCode);先对skucode求hash值看是否是同一个对象,如果不相等肯定不是同一个对象,如果相等那么再比较equals方法中Objects.equals(skuCode, that.skuCode);新加元素的属性值和当前集合中元素的属性值是否相同,如果equals结果相同那么就是同一个对象可以去重,如果equals结果不相同那么就不是同一个对象。
所以: 对象相等则hashCode一定相等;hashCode相等对象未必相等。
相等的对象必须具有相等的哈希码。每当equals方法被覆写,通常需要重写hashCode方法从而
保持对象行为的一致性
6.但是为什么hashCode相同的两个对象不一定相等呢?
当我们看hashCode方法的源码是发现
比较hashCode是否相同时,是拿对象的每个属性进行hash求职然后相加,所以如果两个不同的对象如果属性值相同那么这两个对象的hash值也可能相等,但是对象却不是同一个对象