Java8新特性Stream流实例详解

什么是Stream流?

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

Stream的优点:声明性,可复合,可并行。这三个特性使得stream操作更简洁,更灵活,更高效。

Stream的操作有两个特点:可以多个操作链接起来运行,内部迭代。

Stream可分为并行流与串行流,Stream API 可以声明性地通过 parallel() 与sequential() 在并行流与顺序流之间进行切换。串行流就不必再细说了,并行流主要是为了为了适应目前多核机器的时代,提高系统CPU、内存的利用率,并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。java1.8并行流使用的是fork/join框架,关于fork/join框架可参考http://ifeve.com/talk-concurrency-forkjoin/学习。

注意 :

* 1、Stream不会自己存储数据。

* 2、Stream不会改变原对象,他们会返回一个新的Stream。

* 3、Stream操作是延迟的,他们会等到需要的结果时才执行。

* 4、使用并行流并不一定会提高效率,因为jvm对数据进行切片和切换线程也是需要时间的。

本文主要讲 Stream的3个操作步骤:1、创建Stream 2、中间操作3、终止操作。

创建Stream

创建Stream,就是将一个数据源 (如:集合、数组)转化为一个流。

1、通过Collection系列提供的stream()(串行) 或parallelStream()(并行)获取数据流。

2、通过Arrays中的静态方法stream() 获取数据流。

3、通过Stream类中的静态方法of()获取数据流。

 //1、通过Collection系列提供的stream()(串行) 或parallelStream()(并行)获取
    List<String> list = new ArrayList<>();
    Stream<String> stream1 = list.stream();//串行流
    Stream<String> stream2 = list.parallelStream();//并行流
  //2、通过Arrays中的静态方法stream() 获取数据流
    User[] u = new User[2];
    Stream<User> stream3 = Arrays.stream(u);
  //3、通过Stream;类中的静态方法of()
    Stream<String> stream4 = Stream.of("11","2");

中间操作

中间操作,即对数据源进行一系列的操作处理。
多个中间操作可以连接起来性格一条流水线,除非流水线上触发器终止操作,否则中间操作不会执行任何的处理,而是在终止操作时一次性全部处理,成为惰性求值。

筛选和切片

1、filter(predicate)-接收lambda,从流中排除某些元素。

2、limit(n)-截断流,使其元素不超过给定数量。

3、skip(n)-跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流,与limit(n)互补。

4、distinct-筛选,通过流所生成元素的hashcode()和equals()去重复元素。

/**
   * 打印年龄大于18的前4位用户信息(不重复)
   * 并跳过第1个用户
   */
@Test
  public void test1(){
    list.stream()
    .filter((x)->x.getAge()>18)
    .distinct()
    .limit(4)
    .skip(1).forEach(System.out::println);
  }

映射

1、map,接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素。

2、mapToDouble/mapToInt/mapToLong,接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的DoubleStream/IntStream/LongStream。

3 、flatMap,接收一个函数作为参数,将流中的每个值都换成一个流,然后把流连接成一个流。

 @Test
  public void test2(){
    ///map
    list.stream().map(User::getName)
    .forEach(System.out::println);
    //flatMap
    List<List<User>> list1 = new ArrayList<>();
    list1.add(list);
    list1.stream().flatMap(Stream::getNames)
    .forEach(System.out::println);
  }
  public static Stream<String> getNames(List<User> list){
    List<String> list1 = new ArrayList<String>();
    for (User user : list) {
      list1.add(user.getName());
    }
    return list1.stream();
  }

排序

1、sorted(),产生一个新流,其中按自然顺序排序。

2、sorted(Comparator),产生一个新流,其中按比较器顺序排序。

@Test
  public void test3(){
    List<String> list =Arrays.asList("aa","bb","cc","dd");
    list.stream().sorted()
    .forEach(System.out::println);
    //
    list.stream().sorted((x,y) -> {
      if(x.equals(y)){
        return 1;
      }else{
        return -1;
      }
    } ).forEach(System.out::println);
  }

终止操作

终止操作是执行中间操作链,并产生结果(一个新流),数据源本身并不受影响,其结果可以是任何不是流的值。

查找与匹配

1、allMatch,检查是否匹配所有元素。
2、anyMatch,检查是否至少匹配一个元素。
3、noneMatch,检查是否没有匹配所有元素。
4、findFirst,返回第一个元素。
5、findAny,返回当前流中的任意元素。
6、count,返回流中元素的总数。
7、 max,返回流中最大值。
8、min,返回流中最小值。
9、froEach(Consumer c) 内部迭代。

@Test
  public void test4(){
    boolean b = list.stream().
        noneMatch((e) ->
        e.getName().equals("zhao"));
    System.out.println(b);
    Optional<User> op = list.parallelStream()
        .filter((x) -> x.getAge() == 18)
        .findAny();
    System.out.println(op.get());
  }

归约

reduce,可以将流中的值反复结合起来,得到一个值。

@Test
  public void test5(){
    //转List
    List<String> list1 =list.stream()
        .map(User::getName)
        .collect(Collectors.toList()) ;
    list1.forEach(System.out::println);
    //转HashSet
    HashSet<String> set = list.stream().
        map(User::getName)
        .collect(Collectors.toCollection(HashSet::new));
    set.forEach(System.out::println);
    //总数
    Long count = list.stream()
        .collect(Collectors.counting());
    System.out.println(count);
    //平均年龄
    double avAge = list.stream()
        .collect(Collectors.averagingInt(User::getAge));
    System.out.println(avAge);
    //总年龄
    int toAge = list.stream()
        .collect(Collectors.summingInt(User::getAge));
    System.out.println(toAge);
    //最大值
    Optional<User> u = list.stream()
        .collect(Collectors.maxBy((e1,e2)
            -> Integer.compare(e1.getAge(),e2.getAge() )));
    System.out.println(u);
    //平均年龄
    IntSummaryStatistics collect = list.stream()
        .collect(Collectors.summarizingInt(User::getAge));
    System.out.println(collect.getAverage());
    //分组
    Map<Integer, List<User>> l= list.stream()
        .collect(Collectors.groupingBy(User::getAge));
    System.out.println(l);
    //多级分组
    Map<Integer,Map<String,List<User>> > ls= list.stream()
        .collect(Collectors.groupingBy(
            User::getAge,Collectors.groupingBy(User::getSex)));
    System.out.println(ls);
    //分区
    Map<Boolean,List<User>> map= list.stream()
        .collect(Collectors.partitioningBy((x)
            -> x.getAge()>18));
    System.out.println(map);
    //连接字符串
    String str = list.stream().map(User::getName)
        .collect(Collectors.joining(",","-","-"));
    System.out.println(str);
  }

总结

以上所述是小编给大家介绍的Java8新特性Stream流实例详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Java8新特性lambda表达式有什么用(用法实例)

    我们期待了很久lambda为java带来闭包的概念,但是如果我们不在集合中使用它的话,就损失了很大价值.现有接口迁移成为lambda风格的问题已经通过default methods解决了,在这篇文章将深入解析Java集合里面的批量数据操作(bulk operation),解开lambda最强作用的神秘面纱. 1.关于JSR335 JSR是Java Specification Requests的缩写,意思是Java 规范请求,Java 8 版本的主要改进是 Lambda 项目(JSR 335),其

  • 详解java8中的Stream数据流

    Stream是java8引入的一个重度使用lambda表达式的API.Stream使用一种类似用SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象.直观意味着开发者在写代码时只需关注他们想要的结果是什么而无需关注实现结果的具体方式.这一章节中,我们将介绍为什么我们需要一种新的数据处理API.Collection和Stream的不同之处以及如何将StreamAPI应用到我们的编码中. 筛选重复的元素 Stream 接口支持 distinct 的方法, 它会返回一个元素

  • Java8新特性之重复注解(repeating annotations)浅析

    一.什么是重复注解 允许在同一申明类型(类,属性,或方法)的多次使用同一个注解 二.一个简单的例子java 8之前也有重复使用注解的解决方案,但可读性不是很好,比如下面的代码: 复制代码 代码如下: public @interface Authority {     String role();} public @interface Authorities {    Authority[] value();} public class RepeatAnnotationUseOldVersion

  • Java8新特性之Lambda表达式浅析

    说到java 8,首先会想到lambda(闭包)以及虚拟扩展方法(default method),这个特性早已经被各大技术网站炒得沸沸扬扬了,也是我们java 8系列开篇要讲的第一特性(JEP126 http://openjdk.java.net/jeps/126),jdk8的一些库已经应用了lambda表达式重新设计了,理解他对学习java 8新特性有着重要的意义. 一.函数式接口 函数式接口(functional interface 也叫功能性接口,其实是同一个东西).简单来说,函数式接口是

  • JAVA8 十大新特性详解

    "Java is still not dead-and people are starting to figure that out." 本教程将用带注释的简单代码来描述新特性,你将看不到大片吓人的文字. 一.接口的默认方法 Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法,示例如下: 复制代码 代码如下: interface Formula {    double calculate(int a); default do

  • Java8新特性之字符串去重介绍

    8月19日,Oracle发布了JDK 8u20,JDK 8u20包含很多新特性,比如Java编译器更新.支持在运行时通过API来修改MinHeapFreeRatio和MaxHeapFreeRatio参数.新的GC调优指南文档.不过在众多新特性中,最令人期待的还属字符串去重(String Deduplication ).如何减少内存占用一直是一个永恒的话题,而在Java应用中,经常会看到String对象会占用应用30%的内存,它是Java中最常用的对象之一.新的字符串去重特性可以帮助减少应用中St

  • Java8新特性Stream流实例详解

    什么是Stream流? Stream流是数据渠道,用于操作数据源(集合.数组等)所生成的元素序列. Stream的优点:声明性,可复合,可并行.这三个特性使得stream操作更简洁,更灵活,更高效. Stream的操作有两个特点:可以多个操作链接起来运行,内部迭代. Stream可分为并行流与串行流,Stream API 可以声明性地通过 parallel() 与sequential() 在并行流与顺序流之间进行切换.串行流就不必再细说了,并行流主要是为了为了适应目前多核机器的时代,提高系统CP

  • Java8 新特性Lambda表达式实例详解

    Java8 新特性Lambda表达式实例详解 在介绍Lambda表达式之前,我们先来看只有单个方法的Interface(通常我们称之为回调接口): public interface OnClickListener { void onClick(View v); } 我们是这样使用它的: button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { v.setText("

  • C#语法新特性之元组实例详解

    1.元组(Tuple) 元组(Tuple)在4.0 的时候就有了,但元组也有些缺点,如: 1)Tuple 会影响代码的可读性,因为它的属性名都是:Item1,Item2.. . 2)Tuple 还不够轻量级,因为它是引用类型(Class),对于一个变量要使用一个类型,有点太没必要了. 源代码如下: // 摘要: // 提供用于创造元组对象的静态方法.若要浏览此类型的.NET Framework 源代码,请参阅 Reference Source. public static class Tuple

  • java8新特性 stream流的方式遍历集合和数组操作

    前言: 在没有接触java8的时候,我们遍历一个集合都是用循环的方式,从第一条数据遍历到最后一条数据,现在思考一个问题,为什么要使用循环,因为要进行遍历,但是遍历不是唯一的方式,遍历是指每一个元素逐一进行处理(目的),而并不是从第一个到最后一个顺次处理的循环,前者是目的,后者是方式. 所以为了让遍历的方式更加优雅,出现了流(stream)! 1.流的目的在于强掉做什么 假设一个案例:将集合A根据条件1过滤为子集B,然后根据条件2过滤为子集C 在没有引入流之前我们的做法可能为: public cl

  • Java8新特性之默认方法详解

    目录 简介 正文 什么是默认方法 为啥要提供默认方法呢? 如果不提供呢? 主要针对谁? 实现了默认方法的接口和抽象类有区别吗 是不是可以说Java现在也实现了多重继承? 总结 简介 在Java之前,我们接触到的接口,都是只定义方法,不实现方法 (你看下面这几个人,像不像接口) 但是到了Java8就不一样了,因为在接口中新增了默认方法 这样的话,有些活,就可以交给接口自己去做了,而不用实现类去做(Java你这是在收买人心啊) 我们下面以问答的形式来介绍默认方法的相关知识点(据说问答模式可以让人更好

  • Java8新特性Stream短路终端操作实例解析

    这篇文章主要介绍了Java8新特性Stream短路终端操作实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 传入一个谓词,返回传为boolean,如果符合条件,则直接结束流. 匹配所有 allMatch 任意匹配 anymMatch 不匹配 noneMatch 查找首个 findFirst 查找任意 findAny 匹配所有 allMatch /匹配所有 allMatch @Test public void allMatchTest()

  • Java8新特性Stream的完全使用指南

    什么是Stream Stream是Java 1.8版本开始提供的一个接口,主要提供对数据集合使用流的方式进行操作,流中的元素不可变且只会被消费一次,所有方法都设计成支持链式调用.使用Stream API可以极大生产力,写出高效率.干净.简洁的代码. 如何获得Stream实例 Stream提供了静态构建方法,可以基于不同的参数创建返回Stream实例 使用Collection的子类实例调用stream()或者parallelStream()方法也可以得到Stream实例,两个方法的区别在于后续执行

  • Java9新特性Stream流API优化与增强

    目录 1.Stream.takeWhile(Predicate) 2.Stream.dropWhile(Predicate) 3.StreamStream.iterate(T,Predicate,UnaryOperator) 4.StreamStream.ofNullable(T) 5.IntStream,LongStream和DoubleStream方法 我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还

  • PHP关键特性之命名空间实例详解

    命名空间主要是为了解决代码中类和函数可能存在冲突的问题,而这个特性其他语言一早就有,PHP则是姗姗来迟,它的出现催生了 PSR-4 的诞生,从而也催生了 Composer 的兴起,所以是非常重要的特性. 命名空间的定义 命名空间是一个容器,这个容器主要是为了识别其下的类和函数.一旦定义了命名空间,它下面的代码就属于这个命名空间了,所以命名空间的定义要在代码的最开始行. 对于同一个包来说,同一个命名空间或者子命名空间的代码没有必要在一个 PHP 文件中定义,子命名空间下的代码是为了完成特定模块的工

  • c++11 新特性——智能指针使用详解

    c++11添加了新的智能指针,unique_ptr.shared_ptr和weak_ptr,同时也将auto_ptr置为废弃(deprecated). 但是在实际的使用过程中,很多人都会有这样的问题: 不知道三种智能指针的具体使用场景 无脑只使用shared_ptr 认为应该禁用raw pointer(裸指针,即Widget*这种形式),全部使用智能指针 初始化方法 class A { public: A(int size){ this->size = size; } A(){} void Sh

随机推荐