常规元素去重
常用去重6大方法
方式1:遍历原List赋值给新List(保持原序)
```java
public static List ridRepeat1(List<String> list){
List<String> newList = new ArrayList<>();
list.forEach(str -> {
if (!newList.contains(str)) {
newList.add(str);
}
});
return newList;
}
```
方式2:Set集合去重(保持原序)
```java
public static List ridRepeat2(List<String> list){
List<String> newList = new ArrayList<>();
Set<String> newSet = new HashSet<>();
list.forEach(str -> {
if (newSet.add(str)) {
newList.add(str);
}
});
return newList;
}
```
方式3:Set集合去重——HashSet(原序打乱)
```java
public static List ridRepeat3(List<String> list){
//List<String> newList = new ArrayList<>(new HashSet<>(list));
Set<String> newSet = new HashSet<>();
List<String> newList = new ArrayList<>();
newSet.addAll(list);
newList.addAll(newSet);
return newList;
}
```
方式4:Set集合去重——TreeSet(按字典顺序重排序)
```java
public static List ridRepeat4(List<String> list){
List<String> newList = new ArrayList<>(new TreeSet<>(list));
return newList;
}
```
方式5:Set集合去重——LinkedHashSet(保持原序)
```java
public static List ridRepeat5(List<String> list){
List<String> newList = new ArrayList<String>(new LinkedHashSet<String>(list));
return newList;
}
```
方式6:Java8新特性Stream实现去重(保持原序)
```java
List<String> strList = Arrays.asList("asdf", "sf", "pf", "c", "sg", "pg", "asdf", "pg");
List<String> newList = strList.stream().distinct().collect(Collectors.toList());
System.out.println(newList);
```
上面的方法在List元素为基本数据类型及String类型时是可以的,但是如果List集合元素为对象,不会奏效。
不过如果你的实体类对象使用了目前广泛使用的lombok插件相关注解如:@Data,那么就会自动帮你重写了equals与hashcode方法,当然如果你的需求是根据某几个核心字段属性判断去重,那么你就要在该类中自定义重写equals与hashcode方法了。
自定义对象去重
常用去重3大方法
方式1:Set集合去重
-
自定义实体类
package com.neighbor.nbsp.entity;
import java.util.Objects;
/**
* @ClassName User
* @Description TODO 用户实体类$
* @Author charlesYan
* @Date 2020/2/18 11:49
* @Version 1.0
**/
public class User {
private int id;
private int age;
private String name;
public User() {
}
public User(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
地址相等
if (this == o) return true;
//非空性:对于任意非空引用x,x.equals(null)应该返回false
if (o == null || getClass() != o.getClass()) return false;
if(o instanceof User){
User user = (User) o;
//需要比较的字段相等,则这两个对象相等
return age == user.age &&
Objects.equals(name, user.name);
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(age, name);
}
}
-
测试main方法
public static void main(String[] args) {
List<User> userList = new ArrayList<>();
userList.add(new User(1, 90, "ellin"));
userList.add(new User(2, 98, "charles"));
userList.add(new User(3, 78, "frank"));
userList.add(new User(4, 78, "frank"));
userList.add(new User(5, 90, "ellin"));
//使用HashSet-无序
Set<User> userSet = new HashSet<>();
userSet.addAll(userList);
System.out.println(userSet);
//使用LinkedHashSet-有序
List<User> newUserList = new ArrayList<>(new LinkedHashSet<>(userList));
System.out.println(newUserList.toString());
}
方式2:Java8新特性Stream去重
-
特性介绍
该方式不能保持原列表顺序而是使用了TreeSet按照字典顺序排序后的列表,如果需求不需要按原顺序则可直接使用;
要想按原顺序,可以根据上面简写方式**再次加工处理使用stream流的sorted()**相关API写法
-
测试main方法
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;
import static java.util.Comparator.comparing;
public static void main(String[] args) {
//根据name属性去重
List<User> lt = userList.stream().collect(
collectingAndThen(
toCollection(() -> new TreeSet<>(Comparator.comparing(User::getName))), ArrayList::new)
);
System.out.println(lt);
//根据name,age属性去重,无序
List<User> lt2 = userList.stream().collect(
collectingAndThen(
toCollection(() -> new TreeSet<>(
comparing(o -> o.getName() + ";" + o.getAge())
)), ArrayList::new
)
);
System.out.println(lt2);
//根据name,age属性去重,保持原顺序
//该方法执行报错,欢迎大佬指点
List<User> lt3 = userList.stream().collect(
collectingAndThen(
toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getName() + "," + o.getAge()))),
v -> v.stream().sorted().collect(Collectors.toList())
)
);
}
方式3:Java8新特性filter去重
-
实现方式
创建一个方法作为 Stream.filter() 的参数,其返回类型为 Predicate,原理就是判断一个元素能否加入到 Set 中去
-
案例代码
public static void main(String[] args) {
List<User> userList = new ArrayList<>();
userList.add(new User(1, 90, "ellin"));
userList.add(new User(2, 98, "charles"));
userList.add(new User(3, 78, "frank"));
userList.add(new User(4, 78, "frank"));
userList.add(new User(5, 90, "jack"));
userList.add(new User(6, 89, "jack"));
ObjectMapper objectMapper = new ObjectMapper();
System.out.println("去重前:" + objectMapper.writeValueAsString(userList));
List<User> newUserList1 = userList.stream().distinct().collect(Collectors.toList());
System.out.println("distinct去重:" + objectMapper.writeValueAsString(newUserList1));
//将distinctByKey()方法作为filter()的参数,过滤不能加入到set中的元素
List<User> newUserList2 = userList.stream().filter(
distinctByKey(o -> o.getName() + "," + o.getAge())
).collect(Collectors.toList());
System.out.println("自定义方法去重:" + objectMapper.writeValueAsString(newUserList2));
}
//自定义过滤方法
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}
其他:Java8新特性补充
-
案例代码
public static void main(String[] args) {
List<User> userList = new ArrayList<>();
userList.add(new User(1, 90, "ellin"));
userList.add(new User(2, 98, "charles"));
userList.add(new User(3, 78, "frank"));
userList.add(new User(4, 78, "frank"));
userList.add(new User(5, 90, "jack"));
userList.add(new User(6, 89, "jack"));
userList.stream()
.filter(p -> p.getAge() >= 80)//获取所有80岁以上的用户
// .sorted(Comparator.comparing(User::getAge))//依年纪升序排序
.sorted(Comparator.comparing(User::getAge).reversed())//依年纪降序排序
.collect(Collectors.toList())
.forEach(System.out::println);
boolean isAllAdult = userList.stream().
allMatch(p -> p.getAge() > 18);
System.out.println("是否所有的用户都大于18岁" + isAllAdult);
}
源码分析
Effective Java
Java编程思想
参考链接
https://www.cnblogs.com/zjfjava/p/9897650.html