image.png

玩转集合的遍历,筛选、聚合、映射

三、使用

1、遍历(foreach/find/match)

image.png

1.1、遍历 foreach

  1. List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
  2. // 遍历输出符合要求的元素
  3. list.stream().filter((x) -> x % 2 == 0).forEach(System.out::println);
  4. // 匹配任意一个(适用于并行流)
  5. Optional<Integer> any = list.parallelStream().filter(x -> x % 2 == 0).findAny();
  6. System.out.println("符合要求的任意一个元素:" + any.get());
  7. // 判断是否包含符合条件的元素

1.2、是否匹配所有元素 allMatch

allMatch用于判断流中的所有元素是否都满足指定条件,
这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类

  1. List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
  2. boolean isMatch = list.stream().allMatch(x -> x % 2 == 0);
  3. System.out.println("是否匹配所有元素:"+isMatch);

1.3、是否未匹配所有元素:noneMatch

noneMatch与allMatch恰恰相反,它用于判断流中的所有元素是否都不满足指定条件:

  1. List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
  2. boolean isMatch = list.stream().noneMatch(x -> x % 2 == 0);
  3. System.out.println("是否匹配所有元素:"+isMatch);

1.4、是否匹配任一元素:anyMatch

anyMatch用于判断流中是否存在至少一个元素满足指定的条件,
这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类型。

  1. List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
  2. boolean isMatch = list.stream().anyMatch(x -> x % 2 == 0);
  3. System.out.println("是否存在符合条件的元素:"+isMatch);

1.5、获取任一元素findAny

findAny能够从流中随便选一个元素出来,它返回一个Optional类型的元素。

  1. List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
  2. // 匹配任意一个(适用于并行流)
  3. Optional<Integer> any = list.parallelStream().filter(x -> x % 2 == 0).findAny();
  4. System.out.println("符合要求的任意一个元素:" + any.get());

1.6、获取第一个元素

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
//    匹配符合要求的第一个元素
Optional<Integer> first = list.stream().filter((x) -> x % 2 == 0).findFirst();
System.out.println("符合要求的第一个元素:" + first.get());

2、筛选(filter)

筛选,是按照一定的规则校验流中的元素,将符合条件的元素提取到新的流中的操作。

filter 函数接收一个Lambda表达式作为参数,该表达式返回boolean,在执行过程中,流将元素逐一输送给filter,并筛选出执行结果为true的元素。
image.png

案例一:筛选出list集合中的偶数,并打印出来

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
Stream<Integer> stream = list.stream();
//    遍历输出符合要求的元素
stream.filter((x) -> x % 2 == 0).forEach(System.out::println);

运行结果:
image.png

案例二: 筛选员工中工资高于8000的人,并形成新的集合。

形成新集合依赖collect(收集)

List<Person> personList = new ArrayList<>();
personList.add(new Person("Tom", 8900, 21, "male", "New York"));
personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
personList.add(new Person("Lily", 7800, 41, "female", "Washington"));
personList.add(new Person("Anni", 8200, 11, "female", "New York"));
personList.add(new Person("Owen", 9500, 26, "male", "New York"));
personList.add(new Person("Alisa", 7900, 19, "female", "New York"));


List<String> filterList = personList.stream().filter(x -> x.getSalary() > 8000).map(Person::getName)
        .collect(Collectors.toList());
System.out.print("高于8000的员工姓名:" + filterList);

运行结果:
image.png

3、聚合(max/min/count)

max/min/count Java stream中也引入了这些概念和用法,极大地方便了我们对集合、数组的数据统计工作。

案例一:获取**String**集合中最长的元素。

List<String> list1 = Arrays.asList("adnm", "admmt", "pot", "xbangd", "weoujgsd");
Optional<String> max = list1.stream().max(Comparator.comparing(String::length));
Optional<String> min = list1.stream().min(Comparator.comparing(String::length));
System.out.println("最长的字符串:" + max.get());
System.out.println("最短的字符串:" + min.get());

运行结果:
image.png

案例二:获取**Integer**集合中的最大值。

List<Integer> list2 = Arrays.asList(7, 6, 9, 4, 11, 6);
        Optional<Integer> max1 = list2.stream().max(Integer::compareTo);
        // 自定义排序
        Optional<Integer> max2 = list2.stream().max(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        });
        System.out.println("自然排序的最大值:" + max1.get());

运行结果:
image.png

案例三:获取员工工资最高的人。

List<Person> personList = new ArrayList<Person>();
personList.add(new Person("Tom", 8900, 23, "male", "New York"));
personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
personList.add(new Person("Anni", 8200, 24, "female", "New York"));
personList.add(new Person("Owen", 9500, 25, "male", "New York"));
personList.add(new Person("Alisa", 7900, 26, "female", "New York"));

Optional<Person> max3 = personList.stream().max(Comparator.comparingInt(Person::getSalary));
System.out.println("员工工资最大值:" + max3.get().getSalary());

运行结果:
image.png

案例四:计算**Integer**集合中大于6的元素的个数。


List<Integer> list = Arrays.asList(7, 6, 4, 8, 2, 11, 9);
long count = list.stream().filter(x -> x > 6).count();
System.out.println("list中大于6的元素个数:" + count);

运行结果:
image.png

4、映射(map/flatMap)

映射,可以将一个流的元素按照一定的映射规则映射到另一个流中。
分为mapflatMap

  • map:接收一个函数作为参数,该函数会被应用到每个元素上,对流中的每个元素执行一个函数,使得元素转换成另一种类型输出。

流会将每一个元素输送给map函数,并执行map中的Lambda表达式,最后将执行结果存入一个新的流中。
image.png

  • flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

image.png

**

        String[] strArr = { "abcd", "bcdd", "defde", "fTr" };
        List<String> strList = Arrays.stream(strArr).map(String::toUpperCase).collect(Collectors.toList());

        List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11);
        List<Integer> intListNew = intList.stream().map(x -> x + 3).collect(Collectors.toList());

        System.out.println("每个元素大写:" + strList);
        System.out.println("每个元素+3:" + intListNew);

案例二:将员工的薪资全部增加1000

        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
        personList.add(new Person("Anni", 8200, 24, "female", "New York"));
        personList.add(new Person("Owen", 9500, 25, "male", "New York"));
        personList.add(new Person("Alisa", 7900, 26, "female", "New York"));

        // 不改变原来员工集合的方式
        List<Person> personListNew = personList.stream().map(person -> {
            Person personNew = new Person(person.getName(), 0, 0, null, null);
            personNew.setSalary(person.getSalary() + 10000);
            return personNew;
        }).collect(Collectors.toList());
        System.out.println("一次改动前:" + personList.get(0).getName() + "-->" + personList.get(0).getSalary());
        System.out.println("一次改动后:" + personListNew.get(0).getName() + "-->" + personListNew.get(0).getSalary());

        // 改变原来员工集合的方式
        List<Person> personListNew2 = personList.stream().map(person -> {
            person.setSalary(person.getSalary() + 10000);
            return person;
        }).collect(Collectors.toList());
        System.out.println("二次改动前:" + personList.get(0).getName() + "-->" + personListNew.get(0).getSalary());
        System.out.println("二次改动后:" + personListNew2.get(0).getName() + "-->" + personListNew.get(0).getSalary());

不改变原数据,就是在函数之中进行新创建对象,使用新创建的对象进行赋值

案例三:将两个字符数组合并成一个新的字符数组

List<String> list = Arrays.asList("m,k,l,a", "1,3,5,7");
List<String> listNew = list.stream().flatMap(s -> {
    // 将每个元素转换成一个stream
    String[] split = s.split(",");
    return Arrays.stream(split);
}).collect(Collectors.toList());

System.out.println("处理前的集合:" + list);
System.out.println("处理后的集合:" + listNew);

案例四:列出List中各不相同的单词,List集合如下

List<String> list = new ArrayList<String>();
list.add("I am a boy");
list.add("I love the girl");
list.add("But the girl loves another girl");

//实现思路如下:、
//1、将list变成流对象
//2、对每一个流元素进行处理(按照空格进行分词)
//3、将每一个处理完的流元素集合起来转换为一个待处理的新流(使用flatMap)
//4、对新流进行去重操作
//5、输出流
list.stream()
    .map(line->line.split(" "))
    .flatMap(Arrays::stream)
    .distinct()
    .collect(toList());

附录:

[

](https://mp.weixin.qq.com/s/-vvEbf1d4z5Um7qy2zJNkg)