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<Student> 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<Student> 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 <T> Predicate<T> distinctByField(Function<? super T,?> fieldExtractor){
        Map<Object,Boolean> 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的數據。

發佈了51 篇原創文章 · 獲贊 20 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章