Java 8 新特性 —— Stream API

强大的Stream API

所在包为: java.util.stream.*

Stream 是 java 8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的 查找、过滤和映射数据 等操作。使用 Stream api 的操作,就类似使用SQL 执行的数据库查询,。也可以使用 Stream API 来并行执行操作。

简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式

1. 流(Stream) 到底是什么?

​ 流是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。、

​ ”集合讲的是数据,流讲的是计算“

note: ① Stream 不会存储元素

​ ② Stream 不会改变源对象。相反,他们会返回一个持有结果的新的 Stream。

​ ③ Stream 操作时延迟执行的。这意味着他们会等到需要结果的时候才执行。

2. Stream 操作三个步骤

  1. 创建 Stream
  2. 中间操作
  3. 终止操作(终端操作)
2.1 创建 Stream 的方式
// 1. 可以通过 Collection 系列集合提供的 stream() 或 parallelStream()
// stream() 获取串行流;parallelStream() 获取并行流;
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();

// 2. 通过 Arrays 中的静态方法 stream() 获取数据流
Employee [] emps = new Employee[10];
Stream<Employee> stream2 = Arrays.stream(emps);

// 3. 通过 Stream 类中的静态方法 of()
Stream<String> stream3 = Stream.of("a", "b", "c");

// 4. 创建无限流
// 迭代
//        函数式接口
//        Stream<T> iterate(final T seed, final UnaryOperator<T> f)
//
// @FunctionalInterface
// public interface UnaryOperator<T> extends Function<T, T> {
//
//    static <T> UnaryOperator<T> identity() {
//        return t -> t;
//    }
// }
Stream<Integer> stream4 = Stream.iterate(0, (x) -> x+2);

stream4.limit(10).forEach(System.out::println); // 中间操作+终止操作

// 生成
Stream.generate(() -> Math.random()).limit(5).forEach(System.out::println);
2.2 中间操作
  1. /*
        筛选和切片
        filter ——接受 Lambda,从流中排除某些元素
        limit —— 截断流,使其元素不超过给定数量
        skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit() 互补;
        注意该方法所执行的位置, 会在其之前的其他筛选方法之后的结果上进行跳过元素
        distinct —— 筛选,通过流所生成元素的 hashCode() 和 equals() 去重复元素
        (故使用该方法筛选, 需要先重写hashCode, equals )
    */
    Stream<String> stream = list.stream()	
        						.filter((e) -> {
                                    return e.getId() > 1;
                                })
        						.skip(2)
                                .limit(10)
                                .distinct();
    
    /*
        映射
        map —— 接受 lambda 表达式,将元素转换成其他i形式或提取信息。接受一个函数作为参数,该参数会被应用到每一个元素上,并将其映射成一个新的元素。
        flatMap —— 接受一个函数作为参数,将流中的每个值都换成另外一个流,然后把所有流连接成一个流
    */
    public class TestStream02 {
        @Test
        public void test(){
            List<String> list = Arrays.asList("a", "b", "CC", "dd");
    
            Stream<Stream<Character>> streamStream = list.stream()
                .map(TestStream02::filterCharacter);
    
            streamStream.forEach((x) -> {
                x.forEach(System.out::println);
            });		// 终止操作,打印输出
    
            System.out.println("=======================================");
            System.out.println("以上代码效果与以下代码相同");
            System.out.println("=======================================");
            list.stream()
                .flatMap(TestStream02::filterCharacter)
                .forEach(System.out::println);
        }
        public static Stream<Character> filterCharacter(String str){
            // 省略具体实现
        }
    }
    
    /*
        排序
        sorted() —— 自然排序 (Comparable)
        sorted(Comparator com) —— 定制排序(Comparator), 自己实现 Comparator 函数式接口
     */
    List<String> list = Arrays.asList("a", "b", "CC", "dd");
    
    list.stream().sorted().forEach(System.out::println);
    
    System.out.println("====================================");
    
    employees.stream().sorted((e1, e2) -> {
        if(e1.getId() == e2.getId()) {
            return e1.getName().compareTo(e2.getName());
        } else {
            return e1.getId().compareTo(e2.getId());
        }
    }).forEach(System.out::println);
     
    
注:

中间操作 不会执行任何操作;直到发生 终止操作 才一次性执行全部内容,即"惰性求值"

2.3 终止操作(终端操作)
/*
    1. 查找与匹配
    allMatch —— 检查是否匹配所有元素
    anyMatch —— 检查是否至少匹配一个元素
    noneMatch —— 检查是否没有匹配所有元素
    findFirst —— 返回第一个元素
    findAny —— 返回当前流中的任意元素
    count —— 返回流中元素的总个数
    max —— 返回流中最大值
    min —— 返回流中最小值
 */
// allMatch、anyMatch、noneMatch 实现 Predicate 函数式接口做匹配检查
boolean b1 = employees.stream()
                .allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));

List<String> list = Arrays.asList("a", "b", "CC", "dd");
list.stream().findFirst();

list.stream().findAny();
list.stream().count();
Optional<String> op = list.stream().max(String::compareTo);
Optional<String> op = list.stream().min(String::compareTo);


/*
    2. 规约
    reduce(T identity, BinaryOperator) / reduce(BinaryOperator) —— 可以将流中元素反复结合起来,得到一个值
 */
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

// reduce(T identity, BinaryOperator)
// 0 代入 x, list的流一个一个元素代入y, 将计算结果重新代入 x, 将下一个元素代入 y
Integer sum = list.stream().reduce(0, (x, y) -> x+y);

System.out.println("==================================");

Optional<Integer> op = employees.stream().map(Employee::getId).reduce(Integer::sum);
System.out.println("op:" + op.get());
/*
    3. 收集
    collect —— 将流转换为其他形式。接受一个Collector 接口的实现,用于给 Stream 中元素做汇总的方法
 */
public class TestStream04 {

    List<Employee> employees = Arrays.asList(
            new Employee(1, "atom", Employee.Status.BUSY),
            new Employee(2, "jashon", Employee.Status.FREE),
            new Employee(3, "Linus", Employee.Status.VOCATION),
            new Employee(4, "henry", Employee.Status.FREE),
            new Employee(4, "cenry", Employee.Status.VOCATION),
            new Employee(4, "zenry", Employee.Status.BUSY),
            new Employee(3, "Jack", Employee.Status.BUSY)
    );

    @Test
    public void test8() {
        String str = employees.stream().map(Employee::getName)
                .collect(Collectors.joining(",", "-> ", " <-"));
//                .collect(Collectors.joining(","));
        System.out.println(str);
    }


    @Test
    public void test7() {
        // 此方法可获得 test3 中所计算的值
        IntSummaryStatistics iss = employees.stream().collect(Collectors.summarizingInt(Employee::getId));

        System.out.println(iss.getAverage());
        System.out.println(iss.getCount());
        System.out.println(iss.getCount());
        System.out.println(iss.getMax());
        System.out.println(iss.getMin());
    }

    @Test
    public void test6() {
        Map<Boolean, List<Employee>> map = employees.stream()
                .collect(Collectors.partitioningBy((e) -> e.getId() > 3));
        System.out.println(map);
    }

    // 多级分组
    @Test
    public void test5() {

        Map<Employee.Status, Map<String, List<Employee>>> map = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
                    if(((Employee) e).getId() < 3) {
                        return "靠前";
                    } else {
                        return "靠后";
                    }
                })));

        System.out.println(map);

    }

    // 分组
    @Test
    public void test4() {
        Map<Employee.Status, List<Employee>> map = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus));

        System.out.println(map);
    }


    // 计算
    @Test
    public void test3() {
        // 总数
        long count = employees.stream()
                .collect(Collectors.counting());
        System.out.println("total:" + count);

        System.out.println("=======================");

        // 平均值
        Double avg = employees.stream()
                .collect(Collectors.averagingDouble(Employee::getId));
        System.out.println("avg:" + avg);

        System.out.println("=======================");

        // 总和
        Integer sum = employees.stream()
                .collect(Collectors.summingInt(Employee::getId));
        System.out.println("sum:" + sum);

        System.out.println("=======================");

        // 最大值的对象
        Optional<Employee> max = employees.stream()
                .collect(Collectors.maxBy((e1, e2) -> Integer.compare(e1.getId(), e2.getId())));
        System.out.println("最大值: " + max.get());

        System.out.println("=======================");

        // 最小值
        Optional<Integer> min = employees.stream()
                .map(Employee::getId)
                .collect(Collectors.minBy(Integer::compare));
        System.out.println("最小值: " + min.get());
    }

    // 收集获得集合
    @Test
    public void test2() {
        List<String> list = employees.stream().map(Employee::getName).collect(Collectors.toList());
        list.forEach(System.out::println);

        System.out.println("=======================");

        Set<String> set = employees.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
        set.forEach(System.out::println);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值