在项目中经常会遇到这样的场景,就是一个list,根据某种规则,我要去判断里面是不是有重复的项。
难度不高,但有点烦,所以专门开一篇文章来记录一下,争取弄一个相对简洁的写法。
先看一个简单的例子:
//有一个list,里面是long类型的数字集合
List<Long> numbers = new ArrayList<>();
numbers.add(1L);
numbers.add(2L);
numbers.add(2L);
numbers.add(3L);
numbers.add(4L);
numbers.add(5L);
//判断里面是否有重复
DistinctUtil util = new DistinctUtil();
System.out.println(util.distinctList(numbers).size() == numbers.size());
DistinctUtil是另外写的一个工具类,以下是distinctList方法:
public List<T> distinctList(List<T> rawList) {
return rawList.stream().map(item -> item).distinct().collect(Collectors.toList());
}
这是一个泛型方法 distinctList
,它接受一个 List
类型的参数 rawList
,返回一个经过去重处理的 List
。 具体来说,该方法使用 Java 8 中的 Stream API 来对 rawList
进行操作。
首先,使用 stream()
把 rawList
转换为一个 Stream
。然后,我们用map方法对每个元素进行了一个映射,就是把元素本身映射为元素本身,这一步看似无意义,但其实它是为了强制把 List 转化为 Stream。
接下来,在数据流中使用 distinct()
去重,最后用 collect(Collectors.toList())
方法把处理后的数据流转换为 List
类型并返回。
因为numbers是有重复元素的,所以结果是false。
进一步优化,如果的复杂类型怎么办呢?
比如有一个User类:
@Data
@Builder
public class User {
String name;
Integer age;
}
我要根据姓名是否有重复来判断,就得修改一下逻辑。
public List<T> distinctComplexList(List<T> rawList, Function<? super T,?> mapLogic) {
return (List<T>) rawList.stream().map(item -> mapLogic.apply(item)).distinct().collect(Collectors.toList());
}
这个方法可以用来从一个包含复杂元素的列表中提取指定属性,去重并返回新列表。 该方法接收两个参数:原始列表 rawList
和用于提取指定属性的函数接口 mapLogic
。该方法使用 Java 8 的 Stream API 处理原始列表,首先使用 map()
方法对每个元素进行属性提取,然后使用 distinct()
方法去重,最后使用 collect()
方法将 Stream 转换为列表并返回。
测试
//判断里面是否有重复
DistinctUtil<User> util = new DistinctUtil();
List<User> users = Arrays.asList(
User.builder().name("鲁班七号").age(10).build(),
User.builder().name("鲁班七号").age(10).build(),
User.builder().name("安其拉").age(10).build()
);
Function<User, String> getName = User::getName;
System.out.println(util.distinctComplexList(users, User::getName ).size() == users.size());
注意,使用DistinctUtil的时候,一定要加泛型,不然User::getName的使用会有问题,会报一个Non-static method cannot be referenced from a static context的错误。
对应的,可以再封装两个判断是否重复的方法:
public boolean isRepeat(List<T> rawList){
return distinctList(rawList).size() < rawList.size();
}
public boolean isRepeat(List<T> rawList, Function<? super T,?> mapLogic){
return distinctList(rawList).size() < rawList.size();
}
现在还有个问题,每次用这个工具类,还得先new出一个对象来,有点麻烦。
我之前试过,方法如果加了static,就不能用T了。其实这并不是说静态方法不能用类的泛型参数,而是如果你要用类的泛型参数,这个方法也得是泛型方法。
举个栗子:
public static <T> List<T> distinctList(List<T> rawList) {
return rawList.stream().map(item -> item).distinct().collect(Collectors.toList());
}
搞定了。
本文主要就是做一个记录,我是jdk1.7的忠实粉丝,lamda表达式用起来还是有点磕磕绊绊,后面要加油了。