• 前言:

    讲Stream之前,先来用个小需求带入本文。毕竟代码看的最清楚。

  • 正文:

    项目某个页面有个需求,将关键词和集合比对,判断是否存在关键词,这种需求想必是再普通不过,最简单的就是循环迭代了。
    上来就干,普通for循环,判断:

    for (int i = 0; i < airPortModels1.size(); i++) {if (airPortModels1.get(i).getAirport().contains(searchWord)) {searchList.add(airPortModels1.get(i).getAirport());searchAirPort.add(airPortModels1.get(i));}}

    要么就用增强型for循环

    for (SkiModel skiModel : airPortModels1) {if (skiModel.getPark().equals(searchWord)) {searchList.add(skiModel.getPark());searchAirPort.add(skiModel);}}

    都是遍历每个元素,进行比对,而集合内所有元素都是存储于内存中,如果集合比较大,则比较耗费内存,那么可以使用Stream
    利用Stream:

                      airPortModels1.stream().filter(skiModel -> skiModel.getPark().equals(searchWord)).forEach(skiModel -> {searchList.add(skiModel.getPark());searchAirPort.add(skiModel);});
  • Stream,源码分析:
    A sequence of elements supporting sequential and parallel aggregate operations
    一个集合流,支持顺序和并行聚合操作

    Stream理解起来就是高级的迭代器,普通迭代器就是遍历元素,然后逐一进行某个操作;而Stream可以根据一些特定条件,对元素进行操作,例如过滤Value小于5的元素,获取首字母为大写的元素,都可以交给Stream来进行。
    还是以例子来说明:( 后面都会通过这个例子来讲解)

    List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, null);
    list.stream().filter(integer -> integer > 0).count();///过滤出所有大于0的元素,最后得到个数。

    Stream在这里主要做了两件事情。
    第一、把所有元素获取到
    第二、把大于0的元素过滤出来。
    我们最后调用count()就是获取结果,相当于获取新的List的size。只是相当于,仅仅为了利于我们理解方便,实际上,Stream并没有new一个新List。我们要做的事情就是,获取到Stream,告诉Stream我们要做什么,然后问Stream要结果。
    来分析Stream的语法:
    将 list.stream().filter(integer -> integer > 0).count()分为三部分,
    list.stream() ---------先创建Stream
    filter(integer -> integer > 0) --------------转换Stream,将创建的Stream进行转换,返回新的Stream,可以进行多次转换
    count()---------处理Stream,将转换后的Stream进行汇聚,得到想要的结果
    而且最后.count()也是必不可少的,如果不向Stream索取结果,没有需求,它什么都不会干的,就像项目经理向你提需求一样
    所以讲解Stream也分为这三个步骤:

    1.创建Stream:
    1.1通过Collection的stream()方法,Collection对象转换成Stream,也就是例子中的方法

    list.stream();

    default Stream<E> stream() {return StreamSupport.stream(spliterator(), false);}
    1.2 通过Stream的静态方法创建:

    1.2.1 Stream的of方法,共有两个方法,一个接受变长参数,一个固定参数

    public static<T> Stream<T> of(T t) {return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);}@SafeVarargs
    @SuppressWarnings("varargs") // Creating a stream from an array is safe
    public static<T> Stream<T> of(T... values) {return Arrays.stream(values);}

    例如:

    Stream<Integer> list= Stream.of(0,-3,9,20,2);  //固定长度
    Stream<String> list1= Stream.of("fdsfdas","sdfadd"); //变长参数

    1.2.2 Stream的generator方法 可以生成一个无限长度的Stream,但是 Android N之后才可以使用Generate方法

    public static<T> Stream<T> generate(Supplier<T> s) {Objects.requireNonNull(s);return StreamSupport.stream(new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);}

    例如:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {  //Android N之后才可以使用Generate方法Stream.generate(new Supplier<Integer>() {@Overridepublic Integer get() {return (int) Math.random().forEach(System.out::print); //随机生成无限长度的Stream}});}

    或者 lambda表达式

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {Stream.generate(() -> (int) Math.random()).forEach(System.out::print); //随机生成无限长度的Stream}

    如果想要限制Stream的长度,可以使用limit(),后面会讲到

     Stream.generate(new Supplier<Integer>() {@Overridepublic Integer get() {return (int) Math.random();  }}).limit(10).forEach(System.out::print);//生成长度为10的Stream,并打印

    1.2.3 创建一个规律数据的Stream

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {Stream.iterate(1, new UnaryOperator<Integer>() {@Overridepublic Integer apply(Integer integer) {return integer+1;  //打印1到10的数列}}).limit(10).forEach(System.out::print);}
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//打印11个hello字符串Stream.iterate("hello",UnaryOperator.identity()).limit(11).forEach(System.out::print);}
    2.转换Stream:(为了更清晰理解每个方法的含义,每个方法都附带一个例子)

    1.filter 过滤操作
    对Stream中元素使用给定的条件进行过滤,生成只包含符合条件的元素的Stream;

    List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, null);
    list.stream().filter(integer -> integer>0).count();//过滤掉不大于0的元素

    2.map 转换操作

    Arrays.asList("a","b","c","d").stream().map(s->s+"a,").forEach(System.out::print);//打印出:aa,ba,ca,da,

    map具体有三个方法:mapToInt,mapToLong和mapToDouble。见名知意,例如mapToInt就是把原始Stream转换成一个新的Stream,这个新生成的Stream中的元素都是int类型
    例如:

          List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, 12);list.stream().mapToDouble(new ToDoubleFunction<Integer>() {@Overridepublic double applyAsDouble(Integer value) {return value.doubleValue();  //返回所有元素都为Double类型的Stream}});

    3.flatMap 将高纬度变为低纬度

    private static void flatMapStream() {String [] s1 = {"a1","a2","a3"};String [] s2 = {"b1","b2","b3"};String [] s3 = {"c1","c2","c3"};Arrays.asList(s1,s2,s3).stream().flatMap(str -> Stream.of(str)).map(s -> s+"/").forEach(System.out::print);  //打印出a1/a2/a3/b1/b2/b3/c1/c2/c3}

    和map类似,也有flatMapToInt、flatMapToLong 、flatMapToDouble三个方法,不同的是flatmap中每个元素转换后得到的是Stream对象,会把子Stream中的元素压缩到父集合中;
    例如:

     List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, null);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {list.stream().flatMapToInt(new Function<Integer, IntStream>() {@Overridepublic IntStream apply(Integer integer) {return IntStream.of(integer);}});}

    4.distinct 去重
    对Stream中的元素进行去重操作,生成的Stream中没有重复的元素;
    例如:

          List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, null);long count = list.stream().distinct().count();

    5.sorted 排序
    对Stream中元素进行排序,得到排序之后的Stream,有空参和有参两种方法

          //空参List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, 1);List<Integer> list1 = list.stream().sorted().collect(Collectors.toList());//排序得到新的集合
          //有参List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, 1);list.stream().sorted(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return Integer.compare(o1.intValue(), o2.intValue());}}).forEach(System.out::print); //按元素大小排序

    使用sorted()这个方法,要求Stream中的数据必须实现了Comparable接口
    6.limit Stream进行截断操作

          List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, 1);list.stream().limit(3).forEach(System.out::print);//截取前三个元素

    7.skip 跳过 跳过Stream前的n个元素,(如果原Stream中包含的元素个数小于N,那么返回空Stream

       List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, 1);list.stream().skip(2).forEach(System.out::print); //跳过前两个元素,将剩余元素打印出来    List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, 1);list.stream().skip(10).forEach(System.out::print); //元素个数小于跳过的个数,返回空Stream

    8.peek 生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数(Consumer实例),新Stream每个元素被消费的时候都会执行给定的消费函数;

      Stream<Integer> stream = list.stream().peek(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {}});//生成新的Stream,并提供Cunsumer实例

    9.contact 合并操作,将两个Stream合并为一个,且仅仅可以合并两个Stream,

          List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, 1);List<String> list1 = Arrays.asList("a", "b","c","d");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {Stream.concat(list.stream(), list1.stream()).skip(10).forEach(System.out::print); //打印出23455-101abc}
    3.处理Stream

    遍历forEach
    聚合reduce
    Optional类型
    收集collect
    3.1 遍历
    forEach
    forEachOrdered 两个方法
    3.2.聚合 可以实现从一组数据中生成一个数据(共有三种形式)
    T reduce(T identity, BinaryOperator<T> accumulator);Optional<T> reduce(BinaryOperator<T> accumulator);<U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner);

    List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, 1);
    list.stream().skip(4).reduce(1, new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer integer, Integer integer2) {return integer + integer2;  //1和前四个元素的和}});

    3.3 Optional
    Optional是一种容器,可以存储一些值和null。利用这个类,可以进行null的判断,能够有效的避免NullPointerException

    get()`,可以拿到Optional中的值,没有值则抛出空指针异常
    isPresent(),有非空的值,返回true,否则返回false
    ifPresent(),public void ifPresent(Consumer<? super T> consumer)这个方法中需要一个Consumer接口。如果有非空的值,就执行指定的Consumer的方法来处理这个非空的值;如果为空,则啥都不做

    3.4 收集Stream
    可将转换后的Stream转为集合

          List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, 1);if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {List<Integer> list1 = list.stream().skip(5).collect(Collectors.toList());}

    最后,可以组合使用试试

    List<Integer> list = Arrays.asList(2, 3, 4, 55, -1, 0, 1);Stream<String> list1 = Stream.of(Arrays.asList("2", "a", "a", "mm", "mm", "sde", "andoid"))  //创建Stream.skip(1) //跳过第一个元素.distinct()//去重.filter(strings -> strings.size() >= 1)//过滤元素小于1的元素.map(strings -> strings + "hello") //每个元素加上“hello”字符串.sorted((o1, o2) -> Integer.compare(o1.length(), o2.length())); //按字符串长度排序Stream.concat(list1, list.stream()) //合并两个Stream.limit(8) //取前八个元素.forEach(System.out::print);``` //处理Stream,打印每个元素

Java进阶知识 —— Java8 Stream语法相关推荐

  1. Java8 Stream 语法详解 用法实例

    本文将会详细讲解Stream的使用方法(不会涉及Stream的原理,因为这个系列的文章还是一个快速学习如何使用的). 1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A ...

  2. java outputstream api,Java8 stream API以及常用方法

    Java8引入了全新的Stream API,Stream API为Java编程提供了丰富的函数式编程操作. Stream API与Java提供的其他集合类型有本质的区别,具体如下: java.io的I ...

  3. java8 Stream语法详解

    些Stream的例子可能让你产生疑惑,本文将会详细讲解Stream的使用方法(不会涉及Stream的原理,因为这个系列的文章还是一个快速学习如何使用的). 1. Stream初体验 我们先来看看Jav ...

  4. java进阶一 java8的新特性

    前言 前面总结了java基础相关的知识点,包含数据类型.修饰符和string.java三大特性.多线程.IO流,异常等,接下来我们更深一步看看.jdk8发布版已经有一段时间的,里面有些新特性值得去学习 ...

  5. Java进阶知识-数组类型

    前言 本来数组类型应该属于基础部分的知识,我将它写在进阶部分是因为数组既可以是基础数据类型数组,也可以是引用数据类型数组.所以我想先介绍完类与对象的基础之后,再给大家介绍数组.于是,今天这篇内容给大家 ...

  6. Java进阶知识笔记2【Collection、泛型】

    [Collection.泛型] 主要内容 Collection集合 迭代器 增强for 泛型 学习目标 能够说出集合与数组的区别 说出Collection集合的常用功能 能够使用迭代器对集合进行取元素 ...

  7. Java进阶知识 - 多线程与线程间通信

    CountdownLatch, CyclicBarrier 分别适合什么场景呢? 大部分情况下, 子线程只需要关心自身执行的任务. 但在某些复杂的情况下, 需要使用多个线程来协同完成某个任务, 这就涉 ...

  8. JAVA进阶知识学习-day10

    一.缓冲流 1.1 缓冲流,也叫高效流,是对4个基本的流的增强,按照数据类型分类:  字节缓冲流: BufferedInputStream,BufferedOutputStream  字符缓冲流: B ...

  9. Java进阶知识笔记14--【junit、反射、注解】

    今日内容 Junit单元测试 反射 注解 Junit单元测试: 测试分类: 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值. 白盒测试:需要写代码的.关注程序具体的执行流程. Junit ...

最新文章

  1. apache2.0性能优化
  2. 编程软件python怎样开始学-Python 3.7从零开始学
  3. freeyellowe—book_剑桥少儿英语yellow book内容
  4. bzoj 1369: Gem 树形dp
  5. php 管理员表和用户表,求discuz的管理员数据表和用户数据表结构
  6. 调整 Windows系统参数网址
  7. 董明珠回应口罩预约不到:没想到几十万人预约 正提高产能
  8. 数据预处理之独热编码
  9. Elasticsearch 8.x 正式发布!
  10. Python QT学习——一个简单的入门案例(一)
  11. angular-6大主流前端框架(一)
  12. U盘中文件夹变为应用程序exe不能打开怎样修复
  13. 中国山梨酸市场运营动态分析与前景方向预测报告2022-2028年
  14. 同步,异步的定义和区别
  15. 如何给云服务器安装探针
  16. gdal库之ecw光栅图像支持
  17. Android中白天模式与夜间模式的切换
  18. 金蝶kis记账王新建套账的操作方法
  19. 漫画 | 这该死的分布式!
  20. stm32cubeMX学习一、循环点亮两盏LED灯

热门文章

  1. JS怎么把对象进行ASCII码排序?
  2. vue-cli 脚手架安装
  3. js自动计算金额单位
  4. 《iVX 高仿美团APP制作移动端完整项目》08 会员页 标题、会员卡 制作
  5. React中ref的使用方法和使用场景(详解)
  6. Layui-collapse折叠面板:点按钮后自动折叠问题解决
  7. 黑苹果N卡的驱动在2022年6月1日后安装失败的解决办法
  8. Android模拟器上不了网的解决办法
  9. python学习教程16-数据分组,取前三的值
  10. java实验:定义一个People类,为People类派生出一个子类Employee类