在Java开发过程中,我们经常会遇到需要对List进行去重的需求。
其中常见的情况是,将数组去重,或者将对象依据某个字段去重。这两种方式均可用set属性进行处理。
今天讨论,有一个List,且其中的元素是自定义的对象,我们需要根据对象的某两个字段的值来进行去重,并得到去重后的结果。
整理过程如下:
假设需要对人员(User)去重,依据编号(code)和名称(name)去重
List<User> userList = Arrays.asList(new User("1","张三"), new User("2","李四"), new User("2","李四"), new User("2","李四"));
使用Java 8的Stream API来实现去重
1、使用stream()方法将List转换成Stream。
2、使用distinct()方法去除重复的元素。
3、使用collect(Collectors.toList())将去重后的Stream转换成List。
List<User> distinctList = userList.stream().distinct().collect(Collectors.toList());
for (User user : distinctList) {
System.out.println("编号:" + user.getCode() + ",名称:" + user.getName());
}
人员(User.java)
package com;
public class User {
private String code;
private String name;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User() {
}
public User(String code, String name) {
this.code = code;
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
User other = (User) obj;
return code.equals(other.code) && name.equals(other.name);
}
@Override
public int hashCode() {
return Objects.hash(code, name);
}
}
测试类(Test .java)
package com;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Test {
public static void main(String[] args) {
List<User> userList = Arrays.asList(new User("1","张三"), new User("2","李四"), new User("2","李四"), new User("2","李四"));
List<User> distinctList = userList.stream().distinct().collect(Collectors.toList());
for (User user : distinctList) {
System.out.println("编号:" + user.getCode() + ",名称:" + user.getName());
}
}
}
人员(User.java)
package com;
import java.util.Objects;
public class User {
private String code;
private String name;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User() {
}
public User(String code, String name) {
this.code = code;
this.name = name;
}
}
测试类(Test.java)
package com;
import org.apache.commons.lang.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
public class Test {
public static void main(String[] args) {
List<User> userList = Arrays.asList(new User("1","张三"), new User("2","李四"), new User("2","李四"), new User("2","李四"));
List<User> distinctList = removeDuplicateField(userList);
for (User user : distinctList) {
System.out.println("编号:" + user.getCode() + ",名称:" + user.getName());
}
}
private static List<User> removeDuplicateField(List<User> list) {
Set<User> set = new TreeSet<>(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
int compareToResult = 1;
if(StringUtils.equals(o1.getCode(), o2.getCode()) && StringUtils.equals(o1.getName(), o2.getName())) {
compareToResult = 0; // 0:重复
}
return compareToResult;
}
});
set.addAll(list);
return new ArrayList<>(set);
}
}
关键代码:removeDuplicateField
如上removeDuplicateField方法,可将该方法通过反射,修改成动态通用方法。
JAVA通过反射获取和设置Bean属性(总结):https://blog.csdn.net/qq_38254635/article/details/115520411
Java通过反射机制,动态设置对象属性值:https://blog.csdn.net/qq_38254635/article/details/115765808
也就说说,可将compare中的比较方法,通过注解及反射的方式处理,获取Field的注解,根据固定注解进行比较处理,这样可将removeDuplicateField完善成可配置方法。
弊端:如果使用场景较多,可采用配置的方式,如情况单一,从性能方面考虑,建议单独建立比较方法。
1、https://blog.51cto.com/u_16175434/7631997
2、https://code84.com/850204.html
如有不正确之处,还望指正!书写不易,觉得有帮助就点个赞吧!☺☺☺