java8 stream.of_关于Java8-stream的理解

ollection + 数组Collection.stream()

Collection.parallelStream()

Arrays.stream(T array) or Stream.of()流的操作类型Intermediate: 一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历

Terminal: 一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。

还有一种操作被称为 short-circuiting.

常用操作

map

map生成的是个 1:1 映射,每个输入元素,都按照规则转换成为另外一个元素

List books = Lists.newArrayList();

List bookIds = books.stream()

.map(Book::getId) //从 Book对象流 转换成了 Integer 流 .collect(Collectors.toList());

flatMap

和map类似,不同的是其每个元素转换得到的是Stream对象,会把子Stream中的元素压缩到父集合中,是一对多映射关系

class Article {

private List tags;

}

articles.stream()

.flatMap(article -> article.getTags().stream())

.collect(Collectors.toSet());

filter

对原始 Stream 进行某项测试,通过测试的元素被留下来生成一个新 Stream

过滤出符合表达式的元素,而不是过滤掉符合表达式的元素

//留下偶数Integer[] sixNums = {1, 2, 3, 4, 5, 6};

Integer[] evens = Stream.of(sixNums).filter(n -> n%2 == 0).toArray(Integer[]::new);

forEach

forEach 方法接收一个 Lambda 表达式,然后在 Stream 的每一个元素上执行该表达式

findFirst

返回 Stream 的第一个元素,或者空,返回值类型:Optional

findAny、max/min、reduce都是返回Optional

reduce

主要作用是把 Stream元素组合起来。它提供一个起始值(种子),然后依照运算规则(BinaryOperator),和前面 Stream 的第一个、第二个、第n个元素组合。从这个意义上说,字符串拼接、数值的 sum、min、max、average 都是特殊的 reduce。

BinaryOperator: 表示对同一类型的两个操作数的操作,产生与操作数相同类型的结果。 对于操作数和结果都是相同类型的情况。

// 有起始值,返回值不会为空Integer sum = integers.reduce(0, (a, b) -> a+b);

Integer sum = integers.reduce(0, Integer::sum);

// 无起始值,返回可能为空,所以返回的是OptionalsumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();

collectList to List

List bookDTOs = books.stream().map(this::convert2DTO).collect(Collectors.toList());

// Collectors.toSet() 就返回 Set

private BookDTO convert2DTO(Book book) {

// convert Book to BookDTO}List to Map 转成Map

class Book {

private Integer id;

private String name;

}

Map bookMap = books.stream().collect(Collectors.toMap(Book::getId, Function.identity()));List to Map 转成书的ID和书名的Map

class Book {

private Integer id;

private String name;

}

Map bookIdNameMap = books.stream().collect(Collectors.toMap(Book::getId, Book::getName));List to Map> 按书的分类分组

class Book {

private Integer id;

private String name;

private Integer categoryId;

}

Map> categoryBooksMap = books.stream().collect(Collectors.groupingBy(Book::getCategoryId));List to Map> 按书的分类分组,并且将分组结果转成书名

class Book {

private Integer id;

private String name;

private Integer categoryId;

}

Map> categoryBookNamesMap = books.stream().collect(Collectors.groupingBy(Book::getCategoryId, Collectors.mapping(Book::getName, Collectors.toList())));List to Map 按书的分类分组,并且获得每类书的数量

class Book {

private Integer id;

private String name;

private Integer categoryId;

}

Map> categoryBookNamesMap = books.stream().collect(Collectors.groupingBy(Book::getCategoryId, Collectors.counting()));

关于效率

网上有大量流和迭代方式的效率比较,有说高的,有说低的,让人一头雾水的。其实那些实验在设计上就很有问题(比如,业务操作只有一个),搞清楚流的工作原理,就知道为什么人们说他会提高效率了,也知道那些效率上变慢是什么原因了。

现有一个List books,里面有10本书,我们要对每本书顺序执行三种业务操作A(),B(),C(),假设每个业务操作都耗时1秒。使用迭代方式

使用迭代方式时,第一本书完全走完A(),B(),C()三个操作,第二本书才开始进行A(),B(),C(),因此总耗时是:10*(1+1+1)=30秒

使用流

使用流时,当第一本书走完A(),进入B()时,第二本书就可以进入A()进行检查了,如图 ![流的示意图][stream] 所以流的耗时是:10 + 3 = 13 秒

简单粗暴的总结

平时开发大多数情况下还是进行对象的处理,所以大家大可以放心食用流,99%场景都不需要担心效率问题。与此同时流的代码/业务表达能力更强,用的好的可以让你的代码/业务流程赏心悦目。

对了,还能帮助你养成抽方法的习惯 ‍♂️

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值