java 8 stream

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

  • 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缓存

  • Short-circuiting:对一个无限及集合返回有限的数据 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limitbash

Filter

对象匹配过滤数据结构

方法 示意
filter 经过传递一个预期匹配的对象做为参数并返回一个包含全部匹配到的对象的流。
distinct 返回包含惟一元素的流(惟一性取决于元素相等的实现方式)。
limit 返回一个特定上限的流
skip 返回一个丢弃前n个元素的流
List expensiveInvoices
= invoices.stream()
.filter(inv -> inv.getAmount() > 10_000)
.limit(5)
.collect(Collectors.toList());
复制代码

Matching:

匹配是一个判断是否匹配到给定属性的广泛的数据处理模式,表达式最后返回boolean架构

方法 示意
allMacth 流对象每一个都要匹配到
anyMatch 流对象有匹配到就中断
noneMatch 流对象无匹配对象
boolean expensive =
invoices.stream()
.allMatch(inv -> inv.getAmount() > 1_000);
复制代码

Finding

:流接口还提供了像findFirst和findAny等从流中取出任意的元素。它们能与像filter方法相链接。findFirst和findAny都返回一个可选对象,在串行流中二者都是返回第一个对象,在并行流中findAny返回第一个线程处理最快的数据app

方法 示意
findFirst 返回第一个匹配到的对象
findAny 返回第一个匹配到的对象
Optional =
invoices.stream()
.filter(inv ->
inv.getCustomer() == Customer.ORACLE)
.findAny();
复制代码

Mapping

:流支持映射方法,传递一个函数对象做为方法,把流中的元素转换成另外一种类型。这种方法应用于单个元素,将其映射成新元素。框架

方法 示意
map 应用于单个元素,将其映射成新元素。
List ids
= invoices.stream()
.map(Invoice::getId)
.collect(Collectors.toList());
复制代码

Reducing

方法 示意
reduce(BinaryOperator) 一个函数主要用于累和,求最大值。
int product = numbers.stream().reduce(1, (a, b) -> a * b);
int max = numbers.stream().reduce(Integer.MIN_VALUE,
Integer::max);
复制代码

forEach,peek比较

forEach Terminal操做,再也不返回stream对象,forEach循环体内不能修改本身包含的本地变量值,也不能用 break/return 之类的关键字提早结束循环。 peek能够对循环对象二次封装并返回新的对象ide

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

List<Person> persons = new ArrayList();
 for (int i = 1; i <= 5; i++) {
 Person person = new Person(i, "name" + i);
 persons.add(person);
 }
List<Person> personList2 = persons.stream().limit(2).sorted((p1, p2) -> p1.getName().compareTo(p2.getName())).collect(Collectors.toList());
System.out.println(personList2);
复制代码

min/max/distinct(Terminal)

获取最后计算的最小值,最大值和去重复

Collectors

目前为止你所了解的方法都是返回另外一个流或者一个像boolean,int类型的值,或者返回一个可选对象。相比之下,collect方法是一个结束操做,它可使流里面的全部元素汇集到汇总结果。 传递给collect方法参数是一个java.util.stream.Collector类型的对象。Collector对象实际上定义了一个如何把流中的元素汇集到最终结果的方法。最开始,工厂方法Collectors.toList()被用来返回一个描述了如何把流转变成一个List的Collector对象。后来Collectors类又内建了不少类似的collectors变量。例如,你能够用Collectors.groupingBy方法按消费者把发票分组

Map<Customer, List> customerToInvoices
= invoices.stream().collect(Collectors.group
ingBy(Invoice::getCustomer));
复制代码

groupingBy/partitioningBy

Map<Integer, List<Person>> personGroups = Stream.generate(new PersonSupplier()).
 limit(100).
 collect(Collectors.groupingBy(Person::getAge));
Iterator it = personGroups.entrySet().iterator();
while (it.hasNext()) {
 Map.Entry<Integer, List<Person>> persons = (Map.Entry) it.next();
 System.out.println("Age " + persons.getKey() + " = " + persons.getValue().size());
}
复制代码

在使用条件“年龄小于 18”进行分组后能够看到,不到 18 岁的未成年人是一组,成年人是另一组。partitioningBy 实际上是一种特殊的 groupingBy,它依照条件测试的是否两种结果来构造返回的数据结构,get(true) 和 get(false) 能即为所有的元素对象。

map 处理的input和output一一对应

方法 示意
mapToInt 函数体返回值为int类型
mapToDouble 函数体返回值为Double类型。
mapToLong 函数体返回值为Long类型。

flatMap 处理的input和outPut为一对多关系

方法 示意
flatMapToInt 函数体返回值为int类型
flatMapDouble 函数体返回值为Double类型。
flatMapLong 函数体返回值为Long类型。
Stream<List<Integer>> inputStream = Stream.of(
 Arrays.asList(1),
 Arrays.asList(2, 3),
 Arrays.asList(4, 5, 6)
 );
Stream<Integer> outputStream = inputStream.
flatMap((childList) -> childList.stream());
复制代码

Parallel Streams

Stream API 支持方便的数据并行。换句话说,你能够明确地让流管道以并行的方式运行而不用关心底层的具体实现。在这背后,Stream API使用了Fork/Join框架充分利用了你机器的多核架构。 你所须要作的无非是用parallelStream()方法替换stream()方法。 不是全部的都使用并行的方式,以下

  • parallel streams的内部实现依赖于将数据结构划分红可让不一样线程使用的难易程度。像数组这种数据结构很容易划分,而像链表或者文件这种数据结构很难划分
  • 越是计算流中单个元素花费的资源最高,应用并行越有意义。
  • 若是可能的话尽可能用原始数据类型,这样能够占用更少的内存,也更缓存命中率也更高。
  • 流中元素的数据量越大越好,由于并行的成本会分摊到全部元素,并行节省的时间相对会更多。固然,这也跟单个元素计算的成本相关。
  • 通常来讲,核越多越好。
相关文章
相关标签/搜索