Java8中Stream的用法

1.概述

Stream APl ( java.util.stream)把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。也可以使用Stream API来并行执行操作。简言之,Stream API提供了一种高效且易于使用的处理数据的方式。

2.特性

Stream是数据渠道,用于操作数据源(数组,集合)所生成的元素序列
集合着重于数据,Stream着重于计算

  • Stream不会自己存储数据
  • Stream不会自己创建对象,它会将操作后的数据保存到另外一个对象中。
  • 惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算。

3.Stream操作的三个步骤

  1. 创建Stream
  2. 中间操作
  3. 终止操作

3.1 创建Stream

方式1:通过Collection系列集合提供的stream()或parallelStream()

// 1.1可以通过Collection系列集合提供的stream()或parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();

方式2:通过Arrays中的静态方法stream()获取数组流

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

方式3:通过Stream类中的静态方法of()

// 1.3通过Stream类中的静态方法of()
Stream<String> stream3 = Stream.of("aa", "bb", "cc");
stream3.forEach(System.out::println);

3.2 中间操作

中间操作(Intermediate Operations):中间操作会返回一个新的流,一个流可以后面跟随零个或多个intermediate操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后会返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。而是在终端操作开始的时候才真正开始执行。

无状态:指元素的处理不受之前元素的影响;
有状态:指该操作只有拿到所有元素之后才能继续下去。
非短路操作:指必须处理所有元素才能得到最终结果;
短路操作:指遇到某些符合条件的元素就可以得到最终结果,如 A || B,只要A为true,则无需判断B的结果。
创建的Employee集合对象如下:

// 2. 中间操作
List<Employee> emps = Arrays.asList(
new Employee(102, "李四", 59, 6666.66),
new Employee(101, "张三", 18, 9999.99),
new Employee(103, "王五", 28, 3333.33),
new Employee(104, "赵六", 8, 7777.77),
new Employee(104, "赵六", 8, 7777.77),
new Employee(104, "赵六", 8, 7777.77),
new Employee(105, "田七", 38, 5555.55)
);

筛选与切片
filter:过滤流中的某些元素
limit(n):获取n个元素
skip(n):跳过n元素,配合limit(n)可实现分页
distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素

	//筛选与切片
List<Employee> list = EmployeeData.emps;
//filter(Predicate p)--接收lambda,从流中排除某些元素
Stream<Employee> stream = list.stream();
//查询薪资大于7000
stream.filter(e -> e.getSalary() > 7000).forEach(System.out::println);
System.out.println();
//limit(n)截断流,使其元素不超过给定数量
list.stream().limit(3).forEach(System.out::println);
System.out.println();
//skip(n)跳过元素,返回一个扔掉了前n个元素的流,如果元素不足n个,则返回空
list.stream().skip(3).forEach(System.out::println);
System.out.println();
//distinct()筛选,用过流所生成元素的hashCode()和equals()去除重复元素
list.stream().distinct().forEach(System.out::println);

映射
map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

        List<String> list = Arrays.asList("a,b,c", "1,2,3");

        //将每个元素转成一个新的且不带逗号的元素
Stream<String> s1 = list.stream().map(s -> s.replaceAll(",", ""));
s1.forEach(System.out::println); // abc 123 Stream<String> s3 = list.stream().flatMap(s -> {
//将每个元素转换成一个stream
String[] split = s.split(",");
Stream<String> s2 = Arrays.stream(split);
return s2;
});
s3.forEach(System.out::println); // a b c 1 2 3

排序

        //sorted()-自然排序
List<Integer> list3 = Arrays.asList(12, 31, 42, 123, 13, 51);
list3.stream().sorted().forEach(System.out::println); //sorted(Comparator com)-定制排序
list3.stream().sorted((i1,i2)->-(i1-i2)).forEach(System.out::println);
list.stream()
.sorted((x, y) -> {
if(x.getAge() == y.getAge()){
return x.getName().compareTo(y.getName());
}else{
return Integer.compare(x.getAge(), y.getAge());
}
}).forEach(System.out::println);

3.3 终止操作

匹配,查找
allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false
noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false
anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false
findFirst:返回流中第一个元素
findAny:返回流中的任意元素
count:返回流中元素的总个数
max:返回流中元素最大值
min:返回流中元素最小值

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

        boolean allMatch = list.stream().allMatch(e -> e > 10); //false
boolean noneMatch = list.stream().noneMatch(e -> e > 10); //true
boolean anyMatch = list.stream().anyMatch(e -> e > 4); //true Integer findFirst = list.stream().findFirst().get(); //1
Integer findAny = list.stream().findAny().get(); //1 long count = list.stream().count(); //5
Integer max = list.stream().max(Integer::compareTo).get(); //5
Integer min = list.stream().min(Integer::compareTo).get(); //1

规约
T reduce(T identity, BinaryOperator accumulator) :可以将流中的元素反复结合起来,得到一个值。返回T。
Optional reduce(BinaryOperator accumulator) :可以将流中的元素反复结合起来,得到一个值。返回Optional。

  		//计算1-10的自然数的和
List<Integer> list= Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream().reduce(0, Integer::sum);
System.out.println(sum);
//计算公司员工总工资
Stream<Double> doubleStream = emps.stream().map(Employee::getSalary);
Optional<Double> sumMoney = doubleStream.reduce(Double::sum);
System.out.println(sumMoney);

什么是Optional类

到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针髯常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java8类库的一部分。

Optional类(java.util.Optional)是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用null表示一个值不存在,现在Optional可以更好的表达这个概念。并且可以避免空指针异常。
Optional类的Javadoc描述如下:这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

收集
collect:接收一个Collector实例,将流中元素收集成另外一个数据结构。

  //查找工资大于4000的员工,结果返回一个List或者Set
List<Employee> employeeList = emps.stream().filter(e -> e.getSalary() > 4000).collect(Collectors.toList());
employeeList.forEach(System.out::println);
Set<Employee> employeeSet = emps.stream().filter(e -> e.getSalary() > 4000).collect(Collectors.toSet());
employeeSet.forEach(System.out::println);

Java8中Stream的用法的更多相关文章

  1. Java8中Stream 的一些用法

    数据结构和数据准备 @Data @AllArgsConstructor @NoArgsConstructor static class StreamItem { Integer id; String ...

  2. java8中Stream数据流

    筛选重复的元素 Stream 接口支持 distinct 的方法, 它会返回一个元素(根据流所生成元素的 hashCode和equals方法实现)的流. 例如,以下代码会筛选出列表中所有的偶数,并确保 ...

  3. java8中stream的map和flatmap的理解

    转自https://blog.csdn.net/wynjauu/article/details/78741093 假如我们有这样一个需求给定单词列表["Hello","W ...

  4. 深入理解Java8中Stream的实现原理

    Stream Pipelines 前面我们已经学会如何使用Stream API,用起来真的很爽,但简洁的方法下面似乎隐藏着无尽的秘密,如此强大的API是如何实现的呢?比如Pipeline是怎么执行的, ...

  5. java8中stream常用方法详解

    map: 用作类型转换 如把集合里面的字符串转为大写,或者一个对象的集合取几个字段转为新的对象集合filter: 过滤 符合条件的集合元素保存下来,不符合条件的去掉flatMap:合并集合,比如Lis ...

  6. 关于JDK8中stream的用法小总结。

    import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; public class Ma ...

  7. 【转】Java8中list转map方法总结

    https://blog.csdn.net/zlj1217/article/details/81611834 背景在最近的工作开发之中,慢慢习惯了很多Java8中的Stream的用法,很方便而且也可以 ...

  8. java8的stream功能及常用方法

    Java8中stream对集合操作做了简化,用stream操作集合能极大程度简化代码.Stream 就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后就用尽了. 一. ...

  9. Java8中的Stream API

    本篇文章继续介绍Java 8的另一个新特性——Stream API.新增的Stream API与InputStream和OutputStream是完全不同的概念,Stream API是对Java中集合 ...

  10. Java中stream的详细用法

    来自于:Java 8 stream的详细用法_旅行者-CSDN博客_java stream 一.概述 Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行 ...

随机推荐

  1. c# reflect里面的getValue()参数

    Type ty = t.GetType(); PropertyInfo[] PropertyInfo = ty.GetProperties(); string Typename = typeof(T) ...

  2. 运用C#编写Http服务器

    什么是HTTP服务器 Web服务器是指驻留于因特网上某种类型计算机的程序.当Web浏览器(客户端)连到服务器上并请求文件时,服务器将处理该请求并将文件反馈到该浏览器上,附带的信息会告诉浏览器如何查看该 ...

  3. Java期末课程设计--购物车的GUI(编辑中)

    实现的功能 基本功能 使用admin登录 对商品表内的商品添加至购物车 结算价格 扩展功能 用户的登录注册(基于数据库) 钱包功能 结算前录入地址信息 丰富GUI(指插入图片) 管理员界面(对商品进行 ...

  4. xd p4 WEB源码拓展

    WEB 源码在安全测试中是非常重要的信息来源,可以用来代码审计漏洞也可以用来做信息突破口,其中 WEB 源码有很多技术需要简明分析. 知识点 关于 WEB 源码目录结构 后台目录.模板目录.数据库目录 ...

  5. nginx配置文件过大导致起不来

    更改src/core/ngx_conf_file.c,默认只有4k,将下面值改大重新编译

  6. Echarts实现不均匀刻度的方法,自定义刻度(转)

    原文地址 今天突然有个我们的咨询公司找我问一个echarts问题,这个问题确实值得一解决,很有意思. 问题是这样的.数据中有很多低于100的数值,但是最高值却能达到14000. data = [93. ...

  7. python IDLE清除窗口内容和new file里代码加行业的操作

    这个其实比较简单,主要是从网上下载好ClearWindow.py这个文件,然后把文件放到./Lib/idlelib下面,同时打开该文件夹下config-extensions.def文件,在文件尾加入下 ...

  8. 简单记录五个Linux设置定时任务的步骤(自动化运维必备)

    这几天我们国庆节休息,但是作为运维工作的同学们是不是也不能闲着,担心工作中是不是有任务在执行中需要维护.于是,我们很多的运维工作都是用的自动化运维监控,如果有故障都会定时的处理和告警的.这个与我们的L ...

  9. surfaceview+mediaplayer

    public class VideosurfaceView extends SurfaceView implements SurfaceHolder.Callback, MediaPlayer.OnP ...

  10. Oracle 计划任务批量清理临时表实例

    昨天发现近一段时间,公司某oracle库数据泵方式备份比之前慢了很多,备份集大小并未增长太多.查看了下发现该用户下存在几十万张表. 一.问题分析 1.查看用户下面的表 select count(*) ...