天天看點

Java8 stream 處理 List 交集、差集、去重

Java8的新特性——Stream常用于處理集合,它不會改變集合原有的結構,優點是Stream的代碼會比用for循環處理更加的簡潔。

1:二個集合的交集

例如:找出兩個班名字相同的學生

@Data
public class User {
    /**
     * 工号
     */
    private String userNo;

    /**
     * 姓名
     */

    private String userName;

    public User(String userNo, String userName) {
        this.userNo = userNo;
        this.userName = userName;
    }

    /**
     * 對象的比較涉及到equals()的重寫, 這裡僅僅比較studentName是否相同
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof User)) {
            return false;
        }
        User user = (User) o;
        return userName.equals(user.getUserName());
    }
}      

交集方法:

/**
     * 取交集方法
     */
    public static void test1() {
        // 一班的學生
        List class01 = new ArrayList<>();
        class01.add(new User("1", "小明"));
        class01.add(new User("2", "小黑"));
        class01.add(new User("3", "大白"));

        // 二班的學生
        List class02 = new ArrayList<>();
        class02.add(new User("1", "小黑"));
        class02.add(new User("2", "大白"));

        // 找兩個班名字相同的同學(取交集),比較用的是重寫的equals()
        List sameName = class01.stream().filter(class02::contains).collect(Collectors.toList());
        // 取出交集學生名稱
        List userNameList = sameName.stream().map(User::getUserName).collect(Collectors.toList());
        System.out.println("交集學生姓名:" + userNameList);
    }      

輸出結果:

交集學生姓名:[小黑, 大白]      

需要注意的是:

  1. ​class01.stream().filter(class02::contains)​

    ​​的​

    ​filter()​

    ​會 保留 符合表達式的結果,這裡面表達式的内容是 2班和1班名字相同的同學
  2. forEach是周遊集合,代替了for循環,代碼更為簡潔
  3. ​collect(Collectors.toList())​

    ​​、​

    ​collect(Collectors.toSet())​

    ​、​

    ​collect(Collectors.toMap())​

    ​将Stream的資料歸集到List、Map、Set等集合

2:二個集合差集

/**
     * 取差集
     */
    public static void test2() {
        List list01 = Arrays.asList("a", "b", "c", "d", "e", "f", "g");
        List list02 = Arrays.asList("a", "c", "f", "d");
        // list01和list02的差集, 僅保留了 b,c
        List result = list01.stream().filter(word -> !list02.contains(word)).collect(Collectors.toList());
        System.out.println("差集結果:" + result);
    }      

輸出結果:

差集結果:[b, e, g]      

表達式 ​

​list01.stream().filter(word-> ! list02.contains(word))​

​​,要找的元素,它的特征是隻存在list01中,但不存在list02中,​

​! list02.contains(word)​

​就是說這個元素不在list02中。

3:集合取重

/**
     * 去重
     */
    public static void test3() {
        List list = Arrays.asList("a", "b", "c", "a", "d", "b");
        System.out.println("去重前:" + list);
        List result = list.stream().distinct().collect(Collectors.toList());
        System.out.print("去重後:" + result);
    }      

輸出結果:

去重後結果:[a, b, c, d]      

4:list.stream()構造方法

​list.stream()​

​它是個Stream的構造方法,Stream的構造方法如下:

4.1 用集合建立Stream

List list=Arrays.asList("a","b","c");
//建立順序流
Stream stream=list.stream();
//建立并行流
Stream parallelStream=list.parallelStream();      

4.2 用數組​

​Arrays.stream(array)​

​建立Stream

int[] array={1,2,3,4,5};
IntStream stream=Arrays.stream(array);      

4.3 用​

​Stream<T> of(T... values)​

​建立Stream

Stream stream=Stream.of(1,2,3,4,5);      

常用的是上面這三種,另外還有​

​iterate()​

​​,​

​generate()​

​,後者是生成随機數,兩個構造方法均産生無限流(即元素的個數是無限的)。

/**
     * Stream list限制數量
     */
    public static void test4() {
        Stream result = Stream.iterate(0, num -> num + 2).limit(5);
        System.out.println(result.collect(Collectors.toList()));
    }