java8 Stream api小记

学着使用stream api,并作一些总结java

很好的中文文档  https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/api

 

流的构成

当咱们使用一个流的时候,一般包括三个基本步骤:数组

获取一个数据源(source)→ 数据转换→执行操做获取想要的结果,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(能够有屡次转换),这就容许对其操做能够像链条同样排列,变成一个管道。数据结构

常见用法多线程

  • Collection.stream()
  • Collection.parallelStream() //并行流,不须要再写多线程代码,全部对它的操做会自动并行进行的
  • Arrays.stream(T array) or Stream.of()

流的操做类型分为两种:less

  • Intermediate:一个流能够后面跟随零个或多个 intermediate 操做。其目的主要是打开流,作出某种程度的数据映射/过滤,而后返回一个新的流,交给下一个操做使用。这类操做都是惰性化的(lazy),就是说,仅仅调用到这类方法,并无真正开始流的遍历。如: map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
  • Terminal:一个流只能有一个 terminal 操做,当这个操做执行后,流就被使用“光”了,没法再被操做。因此这一定是流的最后一个操做。Terminal 操做的执行,才会真正开始流的遍历,而且会生成一个结果,或者一个 side effect。如: forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

 

流的使用详解

常见案例ide

一个很简单的例子,涉及map,collect,forEach函数

List<String> wordList = Arrays.asList("a", "b", "c");
//map把留转换为一个新的对象返回,collect收集器把流中的元素汇总
List<String> output = wordList.stream().map(String::toUpperCase).collect(Collectors.toList());
output.forEach(System.out::println);

map的使用,它的做用就是把 input Stream 的每个元素,映射成 output Stream 的另一个元素。ui

collect:是一个终端操做,它接收的参数是将流中的元素累积到汇总结果的各类方式(称为收集器)spa

预约义收集器包括将流元素归约和汇总到一个值.以下

工厂方法

返回类型

用于

toList

List<T>

把流中全部元素收集到List中

示例:List<Menu> menus=Menu.getMenus.stream().collect(Collector.toList())

toSet

Set<T>

把流中全部元素收集到Set中,删除重复项

示例:Set<Menu> menus=Menu.getMenus.stream().collect(Collector.toSet())

toCollection

Collection<T>

把流中全部元素收集到给定的供应源建立的集合中

示例:ArrayList<Menu> menus=Menu.getMenus.stream().collect(Collector.toCollection(ArrayList::new))

Counting

Long

计算流中元素个数

示例:Long count=Menu.getMenus.stream().collect(counting);

SummingInt

Integer

对流中元素的一个整数属性求和

示例:Integer count=Menu.getMenus.stream().collect(summingInt(Menu::getCalories))

averagingInt

Double

计算流中元素integer属性的平均值

示例:Double averaging=Menu.getMenus.stream().collect(averagingInt(Menu::getCalories))

Joining

String

链接流中每一个元素的toString方法生成的字符串

示例:String name=Menu.getMenus.stream().map(Menu::getName).collect(joining(“, ”))

maxBy

Optional<T>

一个包裹了流中按照给定比较器选出的最大元素的optional
若是为空返回的是Optional.empty()

示例:Optional<Menu> fattest=Menu.getMenus.stream().collect(maxBy(Menu::getCalories))

minBy

Optional<T>

一个包裹了流中按照给定比较器选出的最大元素的optional
若是为空返回的是Optional.empty()

示例: Optional<Menu> lessest=Menu.getMenus.stream().collect(minBy(Menu::getCalories))

Reducing

归约操做产生的类型

从一个做为累加器的初始值开始,利用binaryOperator与流中的元素逐个结合,从而将流归约为单个值

示例:int count=Menu.getMenus.stream().collect(reducing(0,Menu::getCalories,Integer::sum));

collectingAndThen

转换函数返回的类型

包裹另外一个转换器,对其结果应用转换函数

示例:Int count=Menu.getMenus.stream().collect(collectingAndThen(toList(),List::size))

groupingBy

Map<K,List<T>>

根据流中元素的某个值对流中的元素进行分组,并将属性值作为结果map的键

示例:Map<Type,List<Menu>> menuType=Menu.getMenus.stream().collect(groupingby(Menu::getType))

partitioningBy

Map<Boolean,List<T>>

根据流中每一个元素应用谓语的结果来对项目进行分区

示例:Map<Boolean,List<Menu>> menuType=Menu.getMenus.stream().collect(partitioningBy(Menu::isType));

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

filter的使用

Integer[] sixNuMS = {1, 2, 3, 4, 5, 6};
List<Integer> evens = Stream.of(sixNuMS).filter(n->n%2==0).collect(Collectors.toList());
evens.forEach(System.out::println);

 

reduce的使用

//拼接字符串
String concact = Stream.of("A","B","C","D").reduce("",String::concat);
System.out.println(concact);
//求最小值
double minValue = Stream.of(1.5,1.0,2.0,-3.0,-2.1).reduce(Double.MAX_VALUE,Double::min);
System.out.println(minValue);
//求和
int sumValue = Stream.of(1,2,3,4).reduce(Integer::sum).get();
System.out.println(sumValue);

这个方法的主要做用是把 Stream 元素组合起来。它提供一个起始值(种子),而后依照运算规则(BinaryOperator),和前面 Stream 的第一个、第二个、第 n 个元素组合

 

sorted的使用

List<Integer> list = Arrays.asList(1, 5, 7, 9, 3, 4);
List<Integer> list2 = list.stream().sorted((a, b) -> a.compareTo(b)).limit(4).collect(Collectors.toList());
System.out.println(list2);

对 Stream 的排序经过 sorted 进行,它比数组的排序更强之处在于你能够首先对 Stream 进行各种 map、filter、limit、skip 甚至 distinct 来减小元素数量后,再排序,这能帮助程序明显缩短执行时间。

 

match 的使用

List<Integer> list = Arrays.asList(1, 5, 7, 9, 3, 4);
boolean all = list.stream().allMatch(n -> n > 10);
System.out.println(all);
boolean any = list.stream().anyMatch(n -> n > 10);
System.out.println(any);
boolean none = list.stream().noneMatch(n -> n > 10);
System.out.println(none);

Stream 有三个 match 方法,从语义上说:

  • allMatch:Stream 中所有元素符合传入的 predicate,返回 true
  • anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true
  • noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true

 

 

 

总结

总之,Stream 的特性能够概括为:

  • 不是数据结构
  • 它没有内部存储,它只是用操做管道从 source(数据结构、数组、generator function、IO channel)抓取数据。
  • 它也毫不修改本身所封装的底层数据结构的数据。例如 Stream 的 filter 操做会产生一个不包含被过滤元素的新 Stream,而不是从 source 删除那些元素。
  • 全部 Stream 的操做必须以 lambda 表达式为参数
  • 不支持索引访问
  • 你能够请求第一个元素,但没法请求第二个,第三个,或最后一个。不过请参阅下一项。
  • 很容易生成数组或者 List
  • 惰性化
  • 不少 Stream 操做是向后延迟的,一直到它弄清楚了最后须要多少数据才会开始。
  • Intermediate 操做永远是惰性化的。
  • 并行能力
  • 当一个 Stream 是并行化的,就不须要再写多线程代码,全部对它的操做会自动并行进行的。
  • 能够是无限的
    • 集合有固定大小,Stream 则没必要。limit(n) 和 findFirst() 这类的 short-circuiting 操做能够对无限的 Stream 进行运算并很快完成。
相关文章
相关标签/搜索