ArrayList 去重
在写java代码中会用到ArrayList,使用过程中有一些比较奇葩的业务,需要对重复的数据去重。
在网上找了几种方法
- 利用HashSet里面的元素不可重复
- 利用list里面contains方法比较是否存在去重
首页我试验了第一种方法
public static void main(String args[]){
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(1);
arrayList.add(3);
arrayList.add(2);
arrayList.add(3);
arrayList = new ArrayList<>(new HashSet<>(arrayList));
for (int i=0;i<arrayList.size();i++){
printlns("arrayList ["+ i +"] = "+arrayList.get(i));
}
}
运行结果
arrayList [0] = 1
arrayList [1] = 2
arrayList [2] = 3
发现确实能行啊,成功了。但是这里排重的是 Integer 类型,如果换成String 类型呢
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("1");
arrayList.add("2");
arrayList.add("2");
arrayList.add("3");
arrayList.add("2");
arrayList.add("1");
运行结果
arrayList [0] = 1
arrayList [1] = 2
arrayList [2] = 3
发现也行,这下放心了,后来在项目中遇到问题,如果换成对象能实现吗
所以我就加入了User对象
static class User{
public User(String name, int age) {
this.name = name;
this.age = age;
}
String name;
int age;
}
并且修改了测试数据
ArrayList<User> arrayList = new ArrayList<>();
arrayList.add(new User("111",10));
arrayList.add(new User("111",10));
arrayList.add(new User("222",20));
arrayList.add(new User("111",10));
arrayList.add(new User("222",20));
arrayList.add(new User("333",30));
arrayList.add(new User("111",10));
arrayList.add(new User("111",10));
arrayList = new ArrayList<>(new HashSet<User>(arrayList));
运行结果
arrayList [0] = 111 , 10
arrayList [1] = 111 , 10
arrayList [2] = 222 , 20
arrayList [3] = 111 , 10
arrayList [4] = 333 , 30
arrayList [5] = 111 , 10
arrayList [6] = 222 , 20
arrayList [7] = 111 , 10
发现去重失败,然后我又看了一下Hastset去重原理:发现HashSet里面比较用equals方法,不对,其实应该是equals和hascode方法。
这里修改一下User类
static class User{
public User(String name, int age) {
this.name = name;
this.age = age;
}
String name;
int age;
@Override
public boolean equals(Object o) {
if(this == o){
return true;
}
if(o == null){
return false;
}
if(getClass() != o.getClass()){
return false;
}
User user = (User) o;
if(age != user.age){
return false;
}
if(name == null){
if(user.name !=null){
return false;
}
}else{
if(!name.equals(user.name)){
return false;
}
}
return true;
}
@Override
public int hashCode() {
return 1;
}
}
运行结果
arrayList [0] = 111 , 10
arrayList [1] = 222 , 20
arrayList [2] = 333 , 30
成功了,干活
Object 中 hasCode
- 在一个进程执行期间,如果一个对象的equals的方法做比较所用到的信息没有被修改的话,则对象调用hashCode方法多次,它必须始终如一的返回同一个整数。
- 如果两个对象根据equals(Object o)方法是相等的,则调用者两个对象中任意一对象的hashCode方法必须产生相同的结果
- 如果两个对象根据equals(Object o)方法是不相等的,则调用这个两个对象中任一个对象的hashCode方法返回值不要产生不同的整数,但是如果不同的话,可以提高散列表的性能。
在HastSet中,基本的操作都是由HashMap低层实现的,因为HastSet底层是用HashMap来存储数据。当向HastSet中添加元素时,首先计算元素的Hashcode值,然后用这个(元素的hashcode)%(HashMap集合的大小)+1计算出这个元素的存储位置,如果这个位置位空,就将元素添加进去;如果不为空,则用equals方法比较元素是否相等,相等就不添加,否则找一个空位添加。
到这里第一种方法
第二种方法,那就来了用到contains方法来判断比较,和第一种方法类似,也是用equals方法来判断。
public static List removeDuplicateWithOrder(List list) {
List newList = new ArrayList();
for (Object o : list) {
if (!newList .contains(o)) newList.add(o);
}
return newList;
}