07. Java8-流式API-终端操作

x33g5p2x  于2021-12-18 转载在 其他  
字(3.6k)|赞(0)|评价(0)|浏览(468)

流的终止操作用于触发流进行流水线处理, 产生流水线处理的结果.结果类型可为任意类型.

1. 常用API

终端API 会触发流进行流水线运算, 常用的终端API 如下:

API 签名描述
boolean allMatch(Predicate<? super T> predicate)短路式检查所有元素是否都符合条件, 遇到一个不符合的则结束
boolean anyMatch(Predicate<? super T> predicate)短路式检查是否至少存在一个元素符合条件,遇到一个符合条件的则结束
boolean noneMatch(Predicate<? super T> predicate)短路式检查是否不存在符合条件的元素, 遇到一个符合条件的则结束
Optional findFirst()返回流中第一个元素
Optional findAny()返回流中任意一个元素
long count()返回流中元素的数量
Optional max(Comparator<? super T> comparator)根据自定义比较规则, 返回流中最大的元素
Optional min(Comparator<? super T> comparator)根据自定义比较规则, 返回流中最小的元素
void forEach(Consumer<? super T> action)内部迭代, 消费流中元素
T reduce(T identity, BinaryOperator accumulator)将流中元素迭代式做二元运算, 最终返回一个值. 有初始值,返回结果必非空
Optional reduce(BinaryOperator accumulator)将流中元素迭代式做二元运算, 最终返回一个值. 无初始值,返回结果可能为空, 所以返回值为Optionanl

2. API 示例

2.1 allMatch

短路式校验,判断流中元素是否全部符合谓词条件.

@Test
public void test_allMatch(){

    boolean b = emps.stream().allMatch((employee -> employee.getAge() > 20));
    System.out.println("所有员工年龄都大于20:" + b);

    boolean b1 = emps.stream().allMatch(employee -> {
        System.out.println("开始校验:" + employee.getName());
        return "Man".equals(employee.getSex());
    });
    System.out.println("所有员工年龄都为男性:" + b1);

}

2.2 anyMatch

短路式校验流中是否存在符合谓词条件的元素.

@Test
public void test_anyMath(){

    boolean b = emps.stream().anyMatch(employee -> {
        System.out.println("开始校验:" + employee.getName());
        return "Woman".equals(employee.getSex());
    });
    System.out.println("员工列表中是否包含女性:" + b);
}

2.3 noneMatch

短路式校验, 判断流中元素是否都不符合条件

@Test
public void test_noneMath(){
    boolean b = emps.stream().noneMatch(employee -> employee.getAge() < 18);
    System.out.println("员工列表中没有18岁以下的员工:" + b);

    boolean b1 = emps.stream().noneMatch(employee -> {
        System.out.println("开始校验:" + employee.getName());
        return employee.getAge() > 30;
    });
    System.out.println("员工列表中没有30岁以下的员工:" + b1);
}

2.4 findFirst

短路式处理, 返回流中第一个元素, 可能为空, 所以返回值为Optional.

@Test
public void test_findFirst(){
    Optional<Employee> opFirst = emps.stream().filter(employee -> "Woman".equals(employee.getSex())).findFirst();
    System.out.println("第一个匹配到的员工:" + opFirst.get());
}

2.5 findAny

短路式处理, 返回流中任意的一个元素

@Test
public void test_findAny(){
    Optional<Employee> opAny = emps.stream().parallel().filter(employee -> "Woman".equals(employee.getSex())).findAny();
    System.out.println("随机匹配到的一个元素:" + opAny.get());
}

2.6 count

返回流中元素数量

@Test
public void test_count(){
    long count = emps.stream().filter(employee -> "Man".equals(employee.getSex())).count();
    System.out.println("员工列表中男性数量为:" + count);
}

2.7 max

自定义排序规则, 返回流中最大的元素

@Test
public void test_max(){
    Optional<Employee> opMax = emps.stream().max((e1, e2) -> e1.getAge().compareTo(e2.getAge()));
    System.out.println("员工列表中年级最大的员工:" + opMax.get());
}

2.8 min

自定义排序规则, 返回流中最小的元素

@Test
public void test_min(){
    Optional<Employee> opMin = emps.stream().min((e1, e2) -> e1.getAge().compareTo(e2.getAge()));
    System.out.println("员工列表中年纪最小的员工:" + opMin.get());
}

2.9 foreach

采用内部迭代方式依次消费流中元素, 也就是遍历流元素. 可以输出流元素信息或者修改流元素属性等操作.

// 内部迭代, 消费流元素
@Test
public void test_foreach(){
    emps.forEach(System.out::println);
}

2.10 reduce

reduce 的计算方式类似于递归, 是拿前面计算的结果和流中下一个元素做运算, 返回结果再与下一个元素做运算, 直到和最后一个元素做完运算, 返回一个结果。

  • 无初始值: 第一轮: 第一个元素做x, 第二个元素做y, 然后x,y 做二元运算; 第二轮: 第一轮结果做x, 第三个元素做y, 然后做二元运算;…
  • 有初始值: 第一轮: 初始值做x, 第二个元素做y, 然后x,y 做二元运算; 第二轮: 第一轮结果做x, 第二个元素做y, 然后做二元运算;…
// 归约
@Test
public void test_reduce(){

    Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

    // 有初始值的reduce, 返回结果必不为空
    Integer sum = stream.reduce(0, (x, y) -> x + y);
    System.out.println("1+2+...+10=" + sum);

    // 无起始值, 结果可能为空, 返回Optional
    Optional<Integer> opSum = stream.reduce((x, y) -> (x + y));
    System.out.println("1+2+...+10=" + opSum.get());
}

相关文章