幾種列表去重的方法
在這里我來分享幾種列表去重的方法,算是一次整理吧,如有紕漏,請不吝賜教。
1. Stream 的distinct()
方法
distinct()
是Java 8 中 Stream 提供的方法,返回的是由該流中不同元素組成的流。distinct()
使用 hashCode()
和 eqauls()
方法來獲取不同的元素。因此,需要去重的類必須實現 hashCode()
和 equals()
方法。換句話講,我們可以通過重寫定制的 hashCode()
和 equals()
方法來達到某些特殊需求的去重。
distinct()
方法聲明如下:
-
Stream<T> distinct();
-
復制代碼
1.1 對於 String
列表的去重
因為 String
類已經覆寫了 equals()
和 hashCode()
方法,所以可以去重成功。
-
-
public void listDistinctByStreamDistinct() {
-
// 1. 對於 String 列表去重
-
List<String> stringList = new ArrayList<String>() {{
-
add( "A");
-
add( "A");
-
add( "B");
-
add( "B");
-
add( "C");
-
}};
-
out.print( "去重前:");
-
for (String s : stringList) {
-
out.print(s);
-
}
-
out.println();
-
stringList = stringList.stream().distinct().collect(Collectors.toList());
-
out.print( "去重后:");
-
for (String s : stringList) {
-
out.print(s);
-
}
-
out.println();
-
}
-
復制代碼
結果如下:
-
去重前:AABBC
-
去重后:ABC
-
復制代碼
1.2 對於實體類列表的去重
注:代碼中我們使用了 Lombok
插件的 @Data
注解,可自動覆寫 equals()
以及 hashCode()
方法。
-
/**
-
* 定義一個實體類
-
*/
-
-
public class Student {
-
private String stuNo;
-
private String name;
-
}
-
復制代碼
-
-
public void listDistinctByStreamDistinct() throws JsonProcessingException {
-
ObjectMapper objectMapper = new ObjectMapper();
-
// 1. 對於 Student 列表去重
-
List<Student> studentList = getStudentList();
-
out.print( "去重前:");
-
out.println(objectMapper.writeValueAsString(studentList));
-
studentList = studentList.stream().distinct().collect(Collectors.toList());
-
out.print( "去重后:");
-
out.println(objectMapper.writeValueAsString(studentList));
-
}
-
復制代碼
結果如下:
-
去重前:[{ "stuNo":"001","name":"Tom"},{"stuNo":"002","name":"Mike"},{"stuNo":"001","name":"Tom"}]
-
去重后:[{ "stuNo":"001","name":"Tom"},{"stuNo":"002","name":"Mike"}]
-
復制代碼
2. 根據 List<Object>
中 Object
某個屬性去重
2.1 新建一個列表出來
-
-
public void distinctByProperty1() throws JsonProcessingException {
-
// 這里第一種方法我們通過新創建一個只有不同元素列表來實現根據對象某個屬性去重
-
ObjectMapper objectMapper = new ObjectMapper();
-
List<Student> studentList = getStudentList();
-
-
out.print( "去重前 :");
-
out.println(objectMapper.writeValueAsString(studentList));
-
studentList = studentList.stream().distinct().collect(Collectors.toList());
-
out.print( "distinct去重后:");
-
out.println(objectMapper.writeValueAsString(studentList));
-
// 這里我們引入了兩個靜態方法,以及通過 TreeSet<> 來達到獲取不同元素的效果
-
// 1. import static java.util.stream.Collectors.collectingAndThen;
-
// 2. import static java.util.stream.Collectors.toCollection;
-
studentList = studentList.stream().collect(
-
collectingAndThen(
-
toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getName))), ArrayList::new)
-
);
-
out.print( "根據名字去重后 :");
-
out.println(objectMapper.writeValueAsString(studentList));
-
}
-
復制代碼
結果如下:
-
去重前 :[{ "stuNo":"001","name":"Tom"},{"stuNo":"001","name":"Tom"},{"stuNo":"003","name":"Tom"}]
-
distinct去重后:[{ "stuNo":"001","name":"Tom"},{"stuNo":"003","name":"Tom"}]
-
根據名字去重后 :[{ "stuNo":"001","name":"Tom"}]
-
復制代碼
2.2 通過 filter()
方法
我們首先創建一個方法作為 Stream.filter()
的參數,其返回類型為 Predicate
,原理就是判斷一個元素能否加入到 Set
中去,代碼如下:
-
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
-
Set<Object> seen = ConcurrentHashMap.newKeySet();
-
return t -> seen.add(keyExtractor.apply(t));
-
}
-
復制代碼
使用如下:
-
-
public void distinctByProperty2() throws JsonProcessingException {
-
// 這里第二種方法我們通過過濾來實現根據對象某個屬性去重
-
ObjectMapper objectMapper = new ObjectMapper();
-
List<Student> studentList = getStudentList();
-
-
out.print( "去重前 :");
-
out.println(objectMapper.writeValueAsString(studentList));
-
studentList = studentList.stream().distinct().collect(Collectors.toList());
-
out.print( "distinct去重后:");
-
out.println(objectMapper.writeValueAsString(studentList));
-
// 這里我們將 distinctByKey() 方法作為 filter() 的參數,過濾掉那些不能加入到 set 的元素
-
studentList = studentList.stream().filter(distinctByKey(Student::getName)).collect(Collectors.toList());
-
out.print( "根據名字去重后 :");
-
out.println(objectMapper.writeValueAsString(studentList));
-
}
-
復制代碼
結果如下:
-
去重前 :[{ "stuNo":"001","name":"Tom"},{"stuNo":"001","name":"Tom"},{"stuNo":"003","name":"Tom"}]
-
distinct去重后:[{ "stuNo":"001","name":"Tom"},{"stuNo":"003","name":"Tom"}]
-
根據名字去重后 :[{ "stuNo":"001","name":"Tom"}]