参考链接: 如何在Java 8中从Stream获取ArrayList

摘要

 Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream。Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。所以说,Java 8 中首次出现的 java.util.stream 是一个函数式语言+多核时代综合影响的产物。

简介

流(Stream)是数据通道,用于操作数据源(集合,数组等)所生成的元素序列 “集合讲的的是数据,流讲的是计算” 注意:  ① Stream不会存储元素  ② Stream不会改变源对象,相反他们会返回一个持有结果的新的Stream  ③ Stream操作是延迟执行的,这意味着他们等到需要结果的时候才会执行(惰性求值)

Stream操作的三个步骤

创建Stream 一个数据源(如:集合,数组)获取一个流中间操作 一个中间操作链,对数据源的数据进行处理终止操作(终端操作) 一个终止操作,执行中间操作链,并产生结果

一:创建Stream

Collection提供了两个方法.stream()与paralleStream()

@org.junit.Test

public void test4(){

List<Integer> list = new ArrayList<>();

Stream<Integer> stream = list.stream();//串行流

Stream<Integer> integerStream = list.parallelStream();//并行流

}

通过Arrays中的Stream()获取一个数组流。

Integer[] integers ={};

Stream<Integer> stream1 = Arrays.stream(integers);

通过Stream类中静态方法of()

Stream<String> stream2 = Stream.of("aaa", "bbb");

创建无限流(无穷的数据)

生成 //通过生成器产生5个10以内的随机数,如果不使用limit就会无限生成10以内随机数

Stream.generate(() -> Math.random() * 10).limit(5).forEach(System.out::println);

----------输出--------

0.8320556195819129

6.260534125204207

7.344094646332503

0.18490598959698068

6.392272744710005

迭代 //通过迭代的方式(一元运算)生成5个数

Stream.iterate(0,x->x+2).limit(5).forEach(System.out::println);

-------------------输出------------

0

2

4

6

8

二:中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理,而在终止操作时一次性全部执行,称为“惰性求值”

List<Integer> list = Arrays.asList(1,2,3,523,21,55);

Stream<Integer> stream3 = list.stream().filter(x -> {

System.out.println("函数执行");

return x > 10;

// stream3.forEach(System.out::println);

上面的代码没有终止操作,当你运行时不会打印任何东西

①筛选与切片

filter----接收Lambda,从流中排除某些元素

//filter()中需要使用断言型接口(Predicate)

List<Integer> list = Arrays.asList(1,2,3,523,21,55);

Stream<Integer> stream3 = list.stream().filter(x -> x > 10);

stream3.forEach(System.out::println);

limit----截断流,使其元素不超过给定数量

List<Integer> list = Arrays.asList(1,2,3,523,21,55);

Stream<Integer> stream3 = list.stream().limit(3);

stream3.forEach(System.out::println);

--------------------输出---------------------

1

2

3

skip----跳过元素返回一个抛弃了前n个元素的流,若流中元素不满足n个,则返回一个空流,与limit形成互补

List<Integer> list = Arrays.asList(1,2,3,523,21,55);

Stream<Integer> stream3 = list.stream().skip(3);

stream3.forEach(System.out::println);

--------------------输出---------------------

523

21

55

distinct----筛选,通过流所所生成元素的hashCode()和equals()去除重复元素

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

Stream<Integer> stream3 = list.stream().distinct();

stream3.forEach(System.out::println);

--------------------输出---------------------

1

2

3

4

注意:自定义的实体类使用distinct去重时,一定要先重写hashCode()和equals()

②映射

map----接收Lambda,将元素转换为其他形式或提取信息时,接收一个函数作为参数,该函数被应用到每个元素上,并将其映射成一个新的元素//map()里面使用函数型接口(Function)

List<String> list = Arrays.asList("aa","bb","cc");

Stream<String> stream3 = list.stream().map(String::toUpperCase);

stream3.forEach(System.out::println);

----------------------输出-----------------------

AA

BB

CC

------------------------------------------------

集合里的每一个元素都会使用到String.toUpperCase()方法

它是以aa作为一个元素,bb作为一个元素

flatMap----接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接一个流List<String> list = Arrays.asList("aa","bb","cc");

Stream<String> stream3 = list.stream().flatMap(l -> {

String[] strings = l.split("");

return Arrays.stream(strings);

});

stream3.forEach(System.out::println);

-------------------输出-----------

a

a

b

b

c

c

-----------------------------------------------

flatMap将原来的流转换为一个新的流并且,是以每一个值为单位的

③排序

sorted() 自然排序 按照Comparable的方式List<String> list = Arrays.asList("aa","cc","bb");

Stream<String> stream3 = list.stream().sorted();

stream3.forEach(System.out::println);

---------------输出-----------

aa

bb

cc

sorted( Comparator com)定制排序 List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

Stream<Integer> stream3 = list.stream().sorted(Integer::compare);

stream3.forEach(System.out::println);

--------------输出--------------

1

2

3

3

6

8

9

终止操作

①查找与匹配

allMatch----检查是否匹配所有元素//allMatch()里面的时断言型接口(Predicate)

List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

boolean b = list.stream().allMatch(x -> x > 3);

System.out.println(b);

------------------输出--------------------

false

//因为不是所有的数都大于3

anyMatch----检查是否有匹配至少一个元素//anyMatch()里面的时断言型接口(Predicate)

List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

boolean b = list.stream().anyMatch(x -> x > 3);

System.out.println(b);

------------------输出--------------------

true

//只要有大于3的数就返回true

noneMatch----检查是否没有匹配的元素//noneMatch()里面的时断言型接口(Predicate)

List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

boolean b = list.stream().noneMatch(x -> x > 3);

System.out.println(b);

------------------输出--------------------

false

//双重否定,返回false就是有匹配的元素

findFirst----返回第一个元素List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

Optional<Integer> first = list.stream().findFirst();

System.out.println(first.get());

-----------------输出----------------

1

findAny----返回当前流中的任意一元素List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

Optional<Integer> first = list.stream().findAny();

System.out.println(first.get());

-----------------输出----------------

1

count-----返回流中元素的总数List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

long count = list.stream().count();

System.out.println(count);

-----------------输出----------------

7

max----返回流中最大值 List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

Optional<Integer> max = list.stream().max(Integer::compareTo);

System.out.println(max.get());

-----------------输出----------------

9

min----返回流中的最小值List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

Optional<Integer> min = list.stream().min(Integer::compareTo);

System.out.println(min.get());

-----------------输出----------------

1

forEach----遍历流中的元素 List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

list.stream().forEach(System.out::println);

-----------------输出----------------

1

3

2

6

8

3

9

//注意:forEach的迭代操作是由Stream API完成的称为内部迭代

//借助于iterator的方式为外部迭代

②归约

reduce(T identity,BinaryOperator)—可以将流中元素反复结合起来得到一个值,返回T List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

Integer reduce = list.stream().reduce(0, (x, y) -> x + y);

System.out.println(reduce);

-----------------输出----------------

32

//根据2元运算将所有的数加起来

//首先以0为x,1为y,结果为1,然后1为x,取3为y,结果为4,以4为x...以此类推

reduce(BinaryOpreator)----可以将流中元素反复结合起来,返回Optional< T > List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

Optional<Integer> reduce = list.stream().reduce((x, y) -> x + y);

System.out.println(reduce.get());

-----------------输出----------------

32

//原理同上,只是这里没有初始值,直接取1为x

//所以ist就有可能为空,当返回的值可能为空时,结果存储在Optional容器中,避免空指针异常

③收集

collect----将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法

Colloector 接口中方法的实现决定了如何对流执行手机操作(如收集到List、Set、Map中)但是Collectots实用类提供了很多静态方法,可以方便的创建常见收集器实例

接下来进行详细介绍 首先创建一个实体类

public class User {

private String name;

private Integer age;

private double salary;

public User(String name, Integer age, double salary) {

this.name = name;

this.age = age;

this.salary = salary;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Integer getAge() {

return age;

}

public void setAge(Integer age) {

this.age = age;

}

public double getSalary() {

return salary;

}

public void setSalary(double salary) {

this.salary = salary;

}

@Override

public String toString() {

return "User{" +

"name='" + name + '\'' +

", age=" + age +

", salary=" + salary +

'}';

}

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

User user = (User) o;

return Double.compare(user.salary, salary) == 0 &&

Objects.equals(name, user.name) &&

Objects.equals(age, user.age);

}

@Override

public int hashCode() {

return Objects.hash(name, age, salary);

}

}

在测试类中准备好数据

public class StreamTest {

List<User> user = Arrays.asList(new User("张三",12,1000.00),

new User ("李四",32,4000),

new User ("王五",40,4000),

new User ("王五",40,4000));

}

根据名称生成一个新的List

List<String> list = user.stream().map(User::getName).collect(Collectors.toList());

list.forEach(System.out::println);

-----------------输出--------------

张三

李四

王五

王五

根据名称生成一个新的Set

Set<String> set = user.stream().map(User::getName).collect(Collectors.toSet());

set.forEach(System.out::println);

-----------------输出--------------

张三

李四

王五

根据名称生成一个新的HashSet

HashSet<String> hashSet = user.stream().map(User::getName).collect(Collectors.toCollection(HashSet::new));

hashSet.forEach(System.out::println);

-----------------输出--------------

李四

张三

王五

获取流中的元素总数

Long count = user.stream().collect(Collectors.counting());

System.out.println(count);

-----------------输出--------------

4

根据工资获取平均值

Double avg = user.stream().collect(Collectors.averagingDouble(User::getSalary));

System.out.println(avg);

-----------------输出--------------

3250.0

根据工资获取总和

Double sum = user.stream().collect(Collectors.summingDouble(User::getSalary));

System.out.println(sum);

-----------------输出--------------

13000.0

根据工资获取组函数

DoubleSummaryStatistics sum = user.stream().collect(Collectors.summarizingDouble(User::getSalary));

System.out.println(sum);

-----------------输出--------------

DoubleSummaryStatistics{count=4, sum=13000.000000, min=1000.000000, average=3250.000000, max=4000.000000}

根据工资获取最大值

Optional<User> max = user.stream().collect(Collectors.maxBy(Comparator.comparingDouble(User::getSalary)));

System.out.println(max.get());

-----------------输出--------------

User{name='李四', age=32, salary=4000.0}

根据工资获取最小值

Optional<User> min = user.stream().collect(Collectors.minBy(Comparator.comparingDouble(User::getSalary)));

System.out.println(min.get());

-----------------输出--------------

User{name='张三', age=12, salary=1000.0}

分组

Map<Double, List<User>> map = user.stream().collect(Collectors.groupingBy(User::getSalary));

System.out.println(map);

-----------------输出--------------

{4000.0=[User{name='李四', age=32, salary=4000.0}, User{name='王五', age=40, salary=4000.0}, User{name='王五', age=40, salary=4000.0}], 1000.0=[User{name='张三', age=12, salary=1000.0}]}

多级分组

Map<Double, Map<String, List<User>>> collect = user.stream().collect(Collectors.groupingBy(User::getSalary, Collectors.groupingBy(

u -> {

if ( u.getAge() <= 12) {

return "青年";

} else if ( u.getAge() <= 32) {

return "中年";

} else {

return "老年";

}

}

)));

System.out.println(collect);

-----------------输出--------------

{4000.0={老年=[User{name='王五', age=40, salary=4000.0}, User{name='王五', age=40, salary=4000.0}], 中年=[User{name='李四', age=32, salary=4000.0}]}, 1000.0={青年=[User{name='张三', age=12, salary=1000.0}]}}

分区

Map<Boolean, List<User>> collect1 = user.stream().collect(Collectors.partitioningBy(e -> e.getSalary() > 3000));

System.out.println(collect1);

-----------------输出--------------

{false=[User{name='张三', age=12, salary=1000.0}], true=[User{name='李四', age=32, salary=4000.0}, User{name='王五', age=40, salary=4000.0}, User{name='王五', age=40, salary=4000.0}]}

连接

String s = user.stream().map(User::getName).collect(Collectors.joining("--"));

System.out.println(s);

-----------------输出--------------

张三--李四--王五--王五

[转载] Java8-Stream API 详解相关推荐

  1. 【java8新特性】——Stream API详解(二)

    一.简介 java8新添加了一个特性:流Stream.Stream让开发者能够以一种声明的方式处理数据源(集合.数组等),它专注于对数据源进行各种高效的聚合操作(aggregate operation ...

  2. Java 8 Stream API详解--转

    原文地址:http://blog.csdn.net/chszs/article/details/47038607 Java 8 Stream API详解 一.Stream API介绍 Java 8引入 ...

  3. Java8 Date API 详解 - LocalDate,LocalDateTime,Instant

    转载来源:https://www.journaldev.com/2800/java-8-date-localdate-localdatetime-instant Java8 Date API 详解 - ...

  4. Java 8 Stream API详解

    Java 8 Stream API详解 一.Stream API介绍 Java 8引入了全新的Stream API,此Stream与Java I/O包里的InputStream和OutputStrea ...

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

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

  6. Stream Api详解

    参考资料: 高级搜索 Stream 1. 什么是stream API Java8提供的stream API可以让程序员像操作数据库一样操作集合.Stream API可以极大提高Java程序员的生产力, ...

  7. java8 Stream语法详解

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

  8. [转载]EXT核心API详解(一)-Ext

    Ext类 addBehaviors( Object obj ) : void 对选择的元素 应用事件侦听器,事件名以@附加在结尾,例如 addBehaviors({    // id=foo下所有的a ...

  9. Java8初体验(二)Stream语法详解(转)

    本文转自http://ifeve.com/stream/ Java8初体验(二)Stream语法详解 感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com 上篇文章Java8初体验( ...

  10. Java8————Stream API

    引言 Java8 加入了java.util.stream包,这个包中的相关API将极大的增强容器对象对元素的操作能力. 它专注于对集合对象进行各种便利.高效的聚合操作,或大批量数据处理. Stream ...

最新文章

  1. js 判断 是否为android
  2. Python数据结构与算法—队列
  3. 【MYSQL】常用命令备忘录
  4. Ubuntu16.04 修改主机名
  5. 对《程序员的自我修养》(龙书)读后思考
  6. React开发(123):ant design学习指南
  7. (数据库系统概论|王珊)第三章关系数据库标准语言SQL-第零节:MYSQL环境安装和表的建立以及一些注意事项
  8. MWC(2) Multiwii初学者详细准备
  9. Mac使用systrace/monitor/adb等工具
  10. XCAP发包工具的使用
  11. 6款主流PDF编辑器测试,快来看看哪一款最适合你吧
  12. DBSCAN聚类算法原理和伪代码
  13. anjuta 连接mysql_深度商店应用Genymotion、Aptana Studio、宝塔Linux面板、Anjuta
  14. msvcr71.dll缺失导致Oracle无法连接
  15. [项目分享]JSP+Servlet+JDBC实现的shine网上书城
  16. Python - turtle画图库 临摹粉色花卉卡片
  17. oracle 查看用户配额,【Quota】获取及调整用户表空间配额方法
  18. zend及Slim 漏洞合集
  19. FileZilla 使用教程
  20. 哈佛大学开放课程:《公正:该如何做是好?》2

热门文章

  1. CSS中div覆盖另一个div
  2. android开发蓝牙自动连接电脑上,Android蓝牙开发之自动连接设备
  3. log4jdbc mysql_[简单]log4jdbc-log4j2配置简记_MySQL
  4. 手把手教你入门Git --- Git使用指南(Linux)
  5. 扫掠两条引导线_《神都夜行录》周年庆点燃线上线下,解读国风二次元IP的成长之路...
  6. c语言给定一个字符串匹配,使用C语言解决字符串匹配问题的方法
  7. 推荐好用的JavaScript模块
  8. 使用mysqladmin命令修改MySQL密码与忘记密码
  9. Android推荐的几本书
  10. 2月第3周国内域名商TOP10:爱名网排名升至第八