Java 8 Stream使用指南

JDK8中首次引入Stream的操作(不是IO的stream),可以让你声明式的方式处理数据。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

简单来说,Stream包装了数据源,让我们更方便和更快速的批量处理数据。

  • Stream不存储数据,也不是一种数据结构,也不修改底层的数据源

创建Stream

常见的创建Stream操作有3种。

1 从数组中创建流,Stream.of

2 从集合中直接获取Stream,Java 8中,Collection接口默认实现了stream方法

3 利用StreamBuilder创建流


    @Test
    public void createStream() {
        // 1. 使用Stream.of创建流
        Stream stream = Stream.of("apple", "banana", "fruit");

        // 2. Java8之后,所有的Collection集合可以使用stream方法获取流
        Stream listGetStream = Arrays.asList("apple", "banana", "fruit").stream();

        // 3. 使用Stream.Buidler创建流
        Stream.Builder streamBuilder = Stream.builder();
        streamBuilder.accept("apple");
        streamBuilder.accept("banana");
        streamBuilder.accept("fruit");
        Stream buildStream = streamBuilder.build();
    }
 
 

Stream操作

基本操作(forEach,findFirst, flatMap,peek)

    @Data
    static class Person {
        int age;
        String name;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }

    @Test
    public void streamForEach() {
        List personList = Arrays.asList(
                new Person("aihe", 23),
                new Person("wuxian", 30),
                new Person("fengxi", 29)
        );

        personList.stream().forEach(p -> {
            p.setAge(p.getAge() + 1);
        });

        for (Person person : personList) {
            System.out.println(person.getAge());
        }
    }

    /**
     * map操作会产生新的Stream
     * collect将Stream中的处理后的数据进行收集
     */
    @Test
    public void streamMap() {
        List personList = Arrays.asList(
                new Person("aihe", 23),
                new Person("wuxian", 30),
                new Person("fengxi", 29)
        );
        List names = personList.stream()
                .map(person -> person.getName())
                .collect(Collectors.toList());
        System.out.println(names);
    }

    @Test
    public void streamFilter() {
        List personList = Arrays.asList(
                new Person("aihe", 23),
                new Person("wuxian", 30),
                new Person("fengxi", 29)
        );
        List person = personList.stream()
                .filter(p -> p.getAge() > 25)
                .filter(p -> p.getName().startsWith("w"))
                .collect(Collectors.toList());
        System.out.println(person);

    }

    /**
     * findFirst。默认返回Optional的值
     */
    @Test
    public void streamFindFirst() {
        Stream stream = Stream.of("1", "2");
        String first = stream
                .findFirst()
                .orElse(null);
        System.out.println(first);
    }

    @Test
    public void streamToArray(){
        String[] strings = Stream.of("1", "2", "3").toArray(String[]::new);
        System.out.println(strings);
    }

    /**
     * 将复杂的数据结构如List等进行平铺操作。如
     * [[1,2],[3,4]]  =>  [1,2,3,4]
     */
    @Test
    public void streamFlatMap(){
        Stream> stream = Stream.of(
                Arrays.asList("1", "2"),
                Arrays.asList("3", "4")
        );
        List collect = stream.flatMap(Collection::stream)
                .collect(Collectors.toList());
        System.out.println(collect);
    }

    /**
     * 上面演示了forEach,foreach是最终的一步操作,返回void类型。
     *  peek操作操作与forEach相同,但是可以多次操作,中间的数据加工阶段
     */
    @Test
    public void streamPeek(){
        List personList = Arrays.asList(
                new Person("aihe", 23),
                new Person("wuxian", 30),
                new Person("fengxi", 29)
        );

        List collect = personList.stream()
                .peek(person -> person.setAge(person.getAge() + 1))
                .peek(person -> person.setName(person.getName().concat(" Hangzhou")))
                .collect(Collectors.toList());
        System.out.println(collect);

    }

Collect操作

 @Test
    public void testCollect(){
        List stringList = Arrays.asList("1", "2", "3");
        String collect = stringList.stream().collect(Collectors.joining(","));
        System.out.println(collect);

        Set setCollect = stringList.stream().collect(Collectors.toSet());
        System.out.println(setCollect);

        ArrayList arrayListCollect = stringList.stream().collect(Collectors.toCollection(ArrayList::new));
        System.out.println(arrayListCollect);

        IntSummaryStatistics intSummaryStatistics = stringList.stream().collect(Collectors.summarizingInt(s -> Integer.parseInt(s)));
        System.out.println(intSummaryStatistics.getSum());

    }

数学操作(排序,最大,最小值)

 @Test
    public void streamMathOp(){
        Stream integerStream = Stream.of(1, 3, 5, 7, 9, 2, 4, 6, 8);
        List integerList = integerStream.sorted((x, y) -> y.compareTo(x)).collect(Collectors.toList());
        System.out.println(integerList);

        Optional max = integerList.stream().max((x, y) -> x - y);
        System.out.println(max.get());

        integerList.add(1);
        integerList.add(2);
        List distinctList = integerList.stream().distinct().collect(Collectors.toList());
        System.out.println(distinctList);
    }

逻辑操作

  /**
     * 逻辑操作
     */
    @Test
    public void streamLogic(){
        List list = Arrays.asList(1, 2, 3);
        boolean allMatch = list.stream().allMatch(i -> i > 2);
        boolean anyMatch = list.stream().anyMatch(i -> i > 2);
        boolean noMatch = list.stream().noneMatch(i -> i > 2);
        System.out.println(allMatch);
        System.out.println(anyMatch);
        System.out.println(noMatch);
    }

GroupBy & Mapping

    @Test
    public void streamGroupBy() {
        List list = Arrays.asList("1", "2", "aihe", "1", "aihe", "3");
        Map> collect = list.stream()
                .collect(
                        Collectors.groupingBy(s -> s, Collectors.mapping(s -> s, Collectors.toList()))
                );
        System.out.println(collect);
    }

无限Stream


    /**
     * 每一个新的元素,调用generate中的Supplier方法进行生成。
     */
    @Test
    public void testGenerate(){
        List collect = Stream.generate(Math::random)
                .limit(5)
                .collect(Collectors.toList());
        System.out.println(collect);

    }

    /**
     * iterate需要一个种子数,然后根据种子元素生成下一个元素
     */
    @Test
    public void testIterate(){
        Stream integerStream = Stream.iterate(2, integer -> integer * 2);
        List list = integerStream.limit(5)
                .collect(Collectors.toList());
        System.out.println(list);
    }

File

    @Test
    public void streamFileRead() throws IOException {
        Stream lines = Files.lines(Paths.get("D:\\code\\daily\\doll-machine\\src\\main\\resources\\application.properties"));
        List stringList = lines.collect(Collectors.toList());
        for (String s : stringList) {
            System.out.println(s);
        }
    }

    @Test
    public void streamFileWrite() throws IOException {
        BufferedWriter bufferedWriter = Files.newBufferedWriter(Paths.get("test.txt"), StandardOpenOption.CREATE,StandardOpenOption.WRITE);
        PrintWriter pw = new PrintWriter(bufferedWriter);
        Stream.of("aihe","wuxian","fengxi")
                .forEach(pw::println);
        pw.close();
    }

最后

这里主要给出了Java 8Stream的一些操作案例,目前比较懒,没有写太多注释,复制下来运行的时候查看效果即可知道具体是用来做什么的。

参考:
https://stackify.com/streams-guide-java-8/
https://www.baeldung.com/java-8-streams
https://martinfowler.com/articles/collection-pipeline/

你可能感兴趣的:(Java 8 Stream使用指南)