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<User> class01 = new ArrayList<>();
        class01.add(new User("1", "小明"));
        class01.add(new User("2", "小黑"));
        class01.add(new User("3", "大白"));

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

        // 找两个班名字相同的同学(取交集),比较用的是重写的equals()
        List<User> sameName = class01.stream().filter(class02::contains).collect(Collectors.toList());
        // 取出交集学生名称
        List<String> 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<String> list01 = Arrays.asList("a", "b", "c", "d", "e", "f", "g");
        List<String> list02 = Arrays.asList("a", "c", "f", "d");
        // list01和list02的差集, 仅保留了 b,c
        List<String> 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<String> list = Arrays.asList("a", "b", "c", "a", "d", "b");
        System.out.println("去重前:" + list);
        List<String> 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<String> list=Arrays.asList("a","b","c");
//创建顺序流
Stream<String> stream=list.stream();
//创建并行流
Stream<String> 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<Integer> stream=Stream.of(1,2,3,4,5);

常用的是上面这三种,另外还有iterate()generate(),后者是生成随机数,两个构造方法均产生无限流(即元素的个数是无限的)。

如果要求数量有限,则需要用 limit 来限制,如:

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

输出结果:[0, 2, 4, 6, 8]

 
posted @ 2022-05-14 18:05  明天,你好啊  阅读(1820)  评论(0编辑  收藏  举报