教你玩转Java8,从零开始认识不一样的Stream

2020-05-23  本文已影响0人  阿博的java技术栈

前言

今天在这里给大家介绍一下关于Java8中Stream,相信Java8的Stream 大家都或多或少的听说过了,但是在实际操作中可能大部分人都没接触过或用的不熟,文章将带大家从零开始使用,循序渐进,带你走向Stream的巅峰。

操作符

什么是操作符呢?操作符就是对数据进行的一种处理工作,一道加工程序;就好像工厂的工人对流水线上的产品进行一道加工程序一样。

Stream的操作符大体上分为两种:中间操作符和终止操作符

中间操作符

对于数据流来说,中间操作符在执行制定处理程序后,数据流依然可以传递给下一级的操作符。

中间操作符包含8种(排除了parallel,sequential,这两个操作并不涉及到对数据流的加工操作):

终止操作符

数据经过中间加工操作,就轮到终止操作符上场了;终止操作符就是用来对数据进行收集或者消费的,数据到了终止操作这里就不会向下流动了,终止操作符只能使用一次。

这里只介绍了Stream,并没有涉及到IntStream、LongStream、DoubleStream,这三个流实现了一些特有的操作符,我将在后续文章中介绍到。

说了这么多,只介绍这些操作符还远远不够;俗话说,实践出真知。那么,Let‘s go。

代码演练

Stream 的一系列操作必须要使用终止操作,否者整个数据流是不会流动起来的,即处理操作不会执行。

map操作将原来的单词 转换成了每个单的长度,利用了String自身的length()方法,该方法返回类型为int。这里我直接使用了lambda表达式,关于lambda表达式 还请读者们自行了解吧。

public class Main {    public static void main(String[] args) {        Stream.of("apple","banana","orange","waltermaleon","grape")                .map(e->e.length()) //转成单词的长度 int                .forEach(e->System.out.println(e)); //输出    }}

当然也可以这样,这里使用了成员函数引用,为了便于读者们理解,后续的例子中将使用lambda表达式而非函数引用。

public class Main {    public static void main(String[] args) {         Stream.of("apple","banana","orange","waltermaleon","grape")                .map(String::length) //转成单词的长度 int                .forEach(System.out::println);    }}

结果如图:

mapToInt 将数据流中得元素转成Int,这限定了转换的类型Int,最终产生的流为IntStream,及结果只能转化成int。

public class Main {    public static void main(String[] args) {         Stream.of("apple", "banana", "orange", "waltermaleon", "grape")                .mapToInt(e -> e.length()) //转成int                .forEach(e -> System.out.println(e));    }}

mapToInt如图:

mapToLong、mapToDouble 与mapToInt 类似

public class Main {    public static void main(String[] args) {         Stream.of("apple", "banana", "orange", "waltermaleon", "grape")                .mapToLong(e -> e.length()) //转成long ,本质上是int 但是存在类型自动转换                .forEach(e -> System.out.println(e));    }}

mapToLong 如图:

public class Main {    public static void main(String[] args) {         Stream.of("apple", "banana", "orange", "waltermaleon", "grape")                .mapToDouble(e -> e.length()) //转成Double ,自动类型转换成Double                .forEach(e -> System.out.println(e));    }}

mapToDouble如图:

public class Main {    public static void main(String[] args) {        Stream.of("a-b-c-d","e-f-i-g-h")                .flatMap(e->Stream.of(e.split("-")))                .forEach(e->System.out.println(e));    }}

flatmap 如图:

public class Main {    public static void main(String[] args) {        Stream.of(1,2,3,4,5,6)                .limit(3) //限制三个                .forEach(e->System.out.println(e)); //将输出 前三个 1,2,3    }}

limit如图:

public class Main {    public static void main(String[] args) {        Stream.of(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1)                .distinct() //去重                .forEach(e->System.out.println(e));    }}

distinct 如图:

public class Main {    public static void main(String[] args) {        Stream.of(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1)                .filter(e->e>=5) //过滤小于5的                .forEach(e->System.out.println(e));    }}

filter 如图:

public class Main {    public static void main(String[] args) {        User w = new User("w",10);        User x = new User("x",11);        User y = new User("y",12);        Stream.of(w,x,y)                .peek(e->{e.setName(e.getAge()+e.getName());}) //重新设置名字 变成 年龄+名字                .forEach(e->System.out.println(e.toString()));    }    static class User {        private String name;        private int age;        public User(String name, int age) {            this.name = name;            this.age = age;        }        public String getName() {            return name;        }        public void setName(String name) {            this.name = name;        }        public int getAge() {            return age;        }        public void setAge(int age) {            this.age = age;        }        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    ", age=" + age +                    '}';        }    }}

peek 如图:

public class Main {    public static void main(String[] args) {        Stream.of(1,2,3,4,5,6,7,8,9)                .skip(4) //跳过前四个                .forEach(e->System.out.println(e)); //输出的结果应该只有5,6,7,8,9    }}

skip 如图:

image.gif

这里Integer 实现了比较器

public class Main {    public static void main(String[] args) {        Stream.of(2,1,3,6,4,9,6,8,0)                .sorted()                .forEach(e->System.out.println(e));    }}

sorted 默认比较器如图:

这里使用自定义比较,当然User 可以实现Comparable 接口

public class Main {    public static void main(String[] args) {        User x = new User("x",11);        User y = new User("y",12);        User w = new User("w",10);        Stream.of(w,x,y)                .sorted((e1,e2)->e1.age>e2.age?1:e1.age==e2.age?0:-1)                .forEach(e->System.out.println(e.toString()));    }    static class User {        private String name;        private int age;        public User(String name, int age) {            this.name = name;            this.age = age;        }        public String getName() {            return name;        }        public void setName(String name) {            this.name = name;        }        public int getAge() {            return age;        }        public void setAge(int age) {            this.age = age;        }        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    ", age=" + age +                    '}';        }    }}

如图:

这里我使用collect 将元素收集到一个set中

public class Main {    public static void main(String[] args) {        Stream.of("apple", "banana", "orange", "waltermaleon", "grape")                .collect(Collectors.toSet()) //set 容器                .forEach(e -> System.out.println(e));    }}

咦?,不是说终止操作符只能使用一次吗,为什么这里调用了forEach 呢?forEach不仅仅是是Stream 中得操作符还是各种集合中得一个语法糖,不信咋们试试。

public class Main {    public static void main(String[] args) {        Set stringSet = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")                .collect(Collectors.toSet()); //收集的结果就是set        stringSet.forEach(e->System.out.println(e)); set的语法糖forEach}

结果如图:

public class Main {    public static void main(String[] args) {        long count = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")                .count();        System.out.println(count);    }}

count 如图:

这里找到第一个元素 apple

public class FindFirst {    public static void main(String[] args) {        Optional stringOptional = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")                .findFirst();        stringOptional.ifPresent(e->System.out.println(e));    }}

findFirst 结果如图:

public class FindAny {    public static void main(String[] args) {        Optional stringOptional = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")                .parallel()                .findAny(); //在并行流下每次返回的结果可能一样也可能不一样        stringOptional.ifPresent(e->System.out.println(e));    }}

findAny 在并行流下 使用结果:

输出了orange

输出了banana

这里 的作用是是判断数据流中 一个都没有与aa 相等元素 ,但是流中存在 aa ,所以最终结果应该是false

public class NoneMatch {    public static void main(String[] args) {        boolean result = Stream.of("aa","bb","cc","aa")                .noneMatch(e->e.equals("aa"));        System.out.println(result);    }}

noneMatch 如图:

public class Main {    public static void main(String[] args) {        Optional integerOptional = Stream.of(0,9,8,4,5,6,-1)                .min((e1,e2)->e1.compareTo(e2));        integerOptional.ifPresent(e->System.out.println(e));    }

min如图:

public class Main {    public static void main(String[] args) {        Optional integerOptional = Stream.of(0,9,8,4,5,6,-1)                .max((e1,e2)->e1.compareTo(e2));        integerOptional.ifPresent(e->System.out.println(e));    }}

max 如图:

这里实现了一个加法,指定了初始化的值

public class Main {    public static void main(String[] args) {        int sum = Stream.of(0,9,8,4,5,6,-1)              .reduce(0,(e1,e2)->e1+e2);        System.out.println(sum);    }}

reduce 如图:

forEach 其实前就已经见过了,对每个数据遍历迭代

这里通过并行的方式输出数字

public class ForEachOrdered {    public static void main(String[] args) {        Stream.of(0,2,6,5,4,9,8,-1)                .parallel()                .forEachOrdered(e->{                    System.out.println(Thread.currentThread().getName()+": "+e);});    }}

forEachOrdered 如图:

public class ToArray {    public static void main(String[] args) {        Object[] objects=Stream.of(0,2,6,5,4,9,8,-1)                .toArray();        for (int i = 0; i < objects.length; i++) {            System.out.println(objects[i]);        }    }}

toArray 如图:

总结

Java8 Stream就带大家认识到这里,如果你能跟着我的文章把每一个例子都敲一遍,相信都能掌握这些操作符的初步用法。

上一篇 下一篇

猜你喜欢

热点阅读