Java1.8—使用Stream通过对象某个字段对集合进行去重

有两种方法实现,一种是通过重写对象的的equals()和hashcode(),再使用distinct,distinct就是通过equals来去重的,下面看一个简单例子。

package com.test.demo;
import lombok.Data;

/**
 * @description:
 * @author: 
 * @create: 2019-11-28 17:08
 **/
@Data
public class Student {
    private String name;
    private int age;
}

这里我使用的lombok的注解@Data,会自动帮我们重写equals和hashcode,toString

package com.test.demo;
import java.util.ArrayList;
import java.util.List;
/**
 * @description:
 * @author: 
 * @create: 2019-11-28 17:10
 **/
public class DistinctByEquals {
    public static void main(String[] args) {
        Student stu1 = new Student();
        stu1.setName("小明");
        stu1.setAge(20);
        Student stu2 = new Student();
        stu2.setName("小明");
        stu2.setAge(20);
        Student stu3 = new Student();
        stu3.setName("小红");
        stu3.setAge(18);
        List students = new ArrayList();
        students.add(stu1);
        students.add(stu2);
        students.add(stu3);
        System.out.println("去重前:");
        students.stream().forEach(x->System.out.println(x.toString()));
        System.out.println("去重后");
        students.stream().distinct().forEach(x->System.out.println(x.toString()));
    }
}

运行结果:


去重前:
Student(name=小明, age=20)
Student(name=小明, age=20)
Student(name=小红, age=18)
去重后
Student(name=小明, age=20)
Student(name=小红, age=18)

Process finished with exit code 0

可以看到,相同对象已经被去掉了。

第二种方法,不需要重写equals和hashcode,我们可以通过自定义filter的过滤规则来实现,这里我们通过name属性来去重,

代码如下

package com.test.demo;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;


/**
 * @description:
 * @author: 
 * @create: 2019-11-28 17:10
 **/
public class DistinctByEquals {
    public static void main(String[] args) {
        Student stu1 = new Student();
        stu1.setName("小华");
        stu1.setAge(22);
        Student stu2 = new Student();
        stu2.setName("小华");
        stu2.setAge(25);
        Student stu3 = new Student();
        stu3.setName("小李");
        stu3.setAge(19);
        List students = new ArrayList();
        students.add(stu1);
        students.add(stu2);
        students.add(stu3);
        System.out.println("去重前:");
        students.stream().forEach(x->System.out.println(x.toString()));
        System.out.println("去重后");
        students.stream().filter(distinctByField(student -> student.getName())).forEach(x->System.out.println(x.toString()));
    }

     static  Predicate distinctByField(Function fieldExtractor){
        Map map = new ConcurrentHashMap<>();
        return t -> map.putIfAbsent(fieldExtractor.apply(t), Boolean.TRUE) == null;
    }
}

运行结果:

去重前:
Student(name=小华, age=22)
Student(name=小华, age=25)
Student(name=小李, age=19)
去重后
Student(name=小华, age=22)
Student(name=小李, age=19)

Process finished with exit code 0

这里主要使用了lambda中的函数式接口,简单来说就是替换了我们原来的匿名类写法,有兴趣的同学可以下去研究研究,这里不多叙述,关于putIfAbsent,该方法作用是 ,如果key不存在或者key已存在但是值为null,就put进去。put进去时返回null,不put进去时返回原值。所以这里就是通过判断返回值是否等于null来判断是否过滤,如果等于null,说明该对象的不重复,返回true,而filter恰好会留下表达式为true的数据。

你可能感兴趣的:(javase,Lambda,函数式接口,Java1.8,去重)