Stream底子学习条记 Stream概念 Stream创建方法 通过Stream静态方法 通过collection方法 通过Arrays静态方法 Stream通用语法 Stream的常用方法 Comparator Collectors 并行操纵 其他阐明
Stream概念
泉源
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理处罚数据。
Stream 利用一种雷同用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 聚集运算和表达的高阶抽象。
概念
Stream(流)是一个来自数据源的元素队列并支持聚合操纵
1) 元素是特定范例的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需盘算。
2) 数据源 流的泉源。 可以是聚集,数组,I/O channel, 产生器generator 等。
3) 聚合操纵 雷同SQL语句一样的操纵, 好比filter, map, reduce, find, match, sorted等。
特点
和从前的Collection操纵差别, Stream操纵尚有两个底子的特性:
1) Pipelining: 中心操纵都会返回流对象本身。 如许多个操纵可以串联成一个管道, 如同流式风格(fluent style)。 如许做可以对操纵举行优化, 好比耽误实行(laziness)和短路( short-circuiting)。
2) 内部迭代: 从前对聚集遍历都是通过Iterator大概For-Each的方式, 显式的在聚集外部举行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
特性
1) stream不存储数据
2) stream不改变源数据
3) stream的耽误实行特性
Stream创建方法
通过Stream静态方法
/**
* 通过一个Supplier函数,无穷天生对象的聚集流,也是一个无穷流
*/
public static Stream generate(Supplier s);
例子:
Stream.generate(Math::random).limit(10).forEach(System.out::println);
/**
* 天生无穷长度的Stream,和generator差别的是,其元素的天生是重复对给定的种子值(seed)调用用户指定函数来天生的。此中包罗的元素可以以为是:seed,f(seed),f(f(seed))无穷循环
*/
public static Stream iterate(final T seed, final UnaryOperator f);
例子:
Stream.iterate(1, e->e+2).limit(10).forEach(System.out::println);
/**
* 通过一个数组获取一个stream,元素为数组的元素,元素必须是对象,而不能是原始数据范例(int、double等)
*/
public static Stream of(T t)
例子:
String[] arrs = new String[]{"a","b","c","d"};
Stream.of(arrs).forEach(System.out::println);
/**
* 通过多个对象入参获取一个stream,元素是入参对象
*/
public static Stream of(T... values);
例子:
Stream.of(new String("one"),new String("two")).forEach(System.out::println);
通过collection方法
可以用过聚集的接口的默认方法,创建一个流;利用这个方法,包罗继续Collection的接口,如:Set,List等等。
/**
* 创建一个流
*/
default Stream stream();
/**
* 创建一个并行流
*/
default Stream parallelStream()
例子:
List strList = new ArrayList();
strList.add("lin");
strList.add("wu");
strList.stream().forEach(System.out::println);
strList.parallelStream().forEach(System.out::println);
通过Arrays静态方法
/**
* 通过一个数据获取流,这泛型的,还存在int、long和double范例
*/
public static Stream stream(T[] array);
例子:
Arrays.stream(new int[]{1,2,3,4}).forEach(System.out::println);
Stream通用语法
Stream的操纵分为3部分:
第一部分是创建一个stream流(可以参照Stream创建方法)
第二部分是stream流的中心操纵,返回的照旧一个stream流(此部分可以有也可以没有)
第三部分是stream流的终极操纵
Stream的常用方法
中心操纵(转换)
无状态操纵
map(转化元素)
/**
* 通过实现Function函数接口,遍历转化元素
*/
Stream map(Function super T, ? extends R> mapper);
filter(过滤元素)
/**
* 通过实现Predicate函数接口,遍历元素,做过滤利用
*/
Stream filter(Predicate super T> predicate);
flatMap(拆解元素)
/**
* 将每个元素作为传播进Function中,末了归入父类流内里
*/
Stream flatMap(Function super T, ? extends Stream extends R>> mapper);
peek(监视元素)
/**
* 此方法重要用于支持调试,您盼望在元素流经管道中的某个点时查察元素
*/
Stream peek(Consumer super T> action);
有状态操纵
limit(截取元素)
/**
* 将取流的前几个元素
*/
Stream limit(long maxSize);
sorted(排序元素)
/**
* 将元素通过天然排序,其元素必须实现Comparable接口
*/
Stream sorted();
/**
* 将元素通过本身实现的Comparable接口举行排序
*/
Stream sorted(Comparator super T> comparator);
distinct(去重元素)
/**
* 将元素做去重操纵,利用equals作为比力
*/
Stream distinct();
skip(跳过元素)
/**
* 跳过前n个元素
*/
Stream skip(long n);
终极操纵(归纳(reduce))
非短路操纵
max(最大值)
/**
* 通过一个Comparator接口,返回最大值元素
*/
Optional max(Comparator super T> comparator);
min(最小值)
/**
* 通过一个Comparator接口,返回最小值元素
*/
Optional min(Comparator super T> comparator);
count(数量)
/**
* 获取元素个数
*/
long count();
reduce(归纳)
明白为归档函数,简朴明白为末了获取一个归纳的值(大概是总和、最大值、最小值等),前面全部函数都可以通过reduce实现,而之以是有上面的函数,是由于常用才界说出来。
/**
* identity为初始值,然后通过BinaryOperator操纵,得到末了的值(与元素雷同范例)
*/
T reduce(T identity, BinaryOperator accumulator);
例子:实现sum操纵
int[] arrInt = {1,3,4,2};
System.out.println("ints sum is:" + Arrays.stream(arrInt).reduce(0, (sum, item) -> sum + item));
/**
* 没有初始值,然后通过BinaryOperator操纵,得到末了的值(是一个Optional值)
*/
Optional reduce(BinaryOperator accumulator);
例子:实现max操纵
int[] arrInt = {1,3,4,2};
System.out.println("ints max is:" + Arrays.stream(arrInt).reduce(0, (item1, item2) -> item1 >item2?item1:item2));
/**
* identity为初始值
* 当stream黑白并行操纵时,用法与2个参数的reduce根本一样,通过BiFunction操纵,得到末了的值(与元素的范例不愿定雷同)
* 当stream是并行操纵时,先是每个线程利用初始值identity分别举行BiFunction操纵,再将得到的每个结果举行BinaryOperator操纵
*/
U reduce(U identity,
BiFunction accumulator,
BinaryOperator combiner);
例子1:通过非并行实现过滤filter操纵
List ints = Arrays.asList(1,2,3,4,5,6,7,8,9,10); BiFunction,Integer,ArrayList> bifun = new BiFunction,Integer,ArrayList>(){
@Override
public ArrayList apply(ArrayList t, Integer u) {
if(u<5)
t.add(u);
return t;
}
};
BinaryOperator> binaryOper = new BinaryOperator>() {
@Override
public ArrayList apply(ArrayList strings, ArrayList strings2) {
return strings;
}
};
System.out.println("ints filter less than 5 is:" + ints.stream().reduce(new ArrayList(),bifun,binaryOper));
collect(网络)
可以明白与reduce一样,但是实现方式大概差别,reduce中通过BiFunction有返回值,而collect通过BiConsumer没有返回值,大概造成影响是对于原始数据范例和String,在collect中每一次BiConsumer操纵都无法保存。reduce恰当不可变容器归约,collect恰当可变容器归约。collect恰当并行。
/**
* supplier为初始值,但与reduce差别是它继承一个表达式
* accumulator,对每个元素举行操纵
* combiner,将全部线程结果举行combiner操纵
*/
R collect(Supplier supplier,
BiConsumer accumulator,
BiConsumer combiner);
/**
* 通过Collector工具类实现与上面方法划一结果
*/
R collect(Collector super T, A, R> collector);
例子:实现filter功能
List ints = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
System.out.println("ints filter less than 5 is:" + ints.stream().parallel().collect(()->new ArrayList(), (array, ar) -> {if (ar<5) array.add(ar);}, (array1, array2) -> array1.addAll(array2)));
短路操纵
findFirst(第一个元素)
/**
* 获取第一个元素
*/
Optional findFirst();
findAny(恣意一个元素)
/**
* 返回这个集会合,取到的任何一个对象。在串行流中取第一个,在并行流中随机取。
*/
Optional findAny();
anyMatch(任何一个元素符合条件)
/**
* 元素中只要一个符合predicate条件,即返回true
*/
boolean anyMatch(Predicate super T> predicate);
allMatch(全部元素符合条件)
/**
* 全部元素中都符合predicate条件,即返回true
*/
boolean allMatch(Predicate super T> predicate);
noneMatch(没有元素符合条件)
/**
* 全部元素中都不符合predicate条件,即返回true
*/
boolean noneMatch(Predicate super T> predicate);
Comparator
Comparator接口,提供了一下静态方法获取comparator。
1) Comparator.reverseOrder()) 天然排序的逆向排序
2) Comparator.comparing(Student::getAge))利用某个属性排序
3) Comparator.comparing(Student::getAge).reversed(),逆向排序
一样平常用于sort操纵
Collectors
Collectors 类实现了许多归约操纵,比方将流转换成聚集和聚合元素。Collectors 可用于返回列表或字符串。一样平常用于collect操纵中。
toList(转换为List)
/**
* 将stream转化为一个List
*/
public static Collector> toList();
toSet(转换为Set)
/**
* 将stream转化为一个Set
*/
public static Collector> toSet();
toMap(转换为Map)
/**
* 将stream转化为一个Map
* keyMapper,是获取key的一个function,假如元素的key存在一样,会报java.lang.IllegalStateException。这是由于没有传入mergeFunction,利用默认的throwingMerger。
* valueMapper,是获取value的一个function
*/
public static
Collector> toMap(Function super T, ? extends K> keyMapper,
Function super T, ? extends U> valueMapper);
/**
* 将stream转化为一个Map
* keyMapper,是获取key的一个function,假如元素的key存在一样,会报java.lang.IllegalStateException
* valueMapper,是获取value的一个function
* mergeFunction,一个BinaryOperator,管理一个重复key报错标题
*/
public static
Collector> toMap(Function super T, ? extends K> keyMapper,
Function super T, ? extends U> valueMapper,
BinaryOperator mergeFunction);
/**
* 将stream转化为一个Map
* keyMapper,是获取key的一个function,假如元素的key存在一样,会报java.lang.IllegalStateException
* valueMapper,是获取value的一个function
* mergeFunction,一个BinaryOperator,管理一个重复key报错标题
* mapSupplier,指定返回Map范例,假如没有,默以为HashMap。
*/
public static >
Collector toMap(Function super T, ? extends K> keyMapper,
Function super T, ? extends U> valueMapper,
BinaryOperator mergeFunction,
Supplier mapSupplier)
例子:
List list = new ArrayList();
list.add(new Person(1, "haha"));
list.add(new Person(2, "rere"));
list.add(new Person(3, "fefe"));
list.add(new Person(1, "linwu"));
list.add(new Person(4, null));
Map mapp = list.stream().collect(Collectors.toMap(Person::getId, Function.identity(),(k,v)->v));
System.out.println(mapp);
System.out.println(mapp.get(1).getName());
averaging(获取均匀值)
有三种,分别为averagingInt、averagingLong、averagingDouble。返回均匀值。
summarizing(获取统计信息)
有三种,分别为summarizingInt、summarizingLong、summarizingDouble。返回一个统计信息,包罗个数,总数等。
groupingBy(分组)
分组功能,返回一个Map,key为泛型,value为一个List。有三种范例,可以支持多层分组。
partitioningBy(分区)
分区功能,是分组功能的一种特殊情况,其map的key是boolean,以是只有true和false。可以支持多层分组。
并行操纵
根据预估的数据量获取最小处理处罚单元的巨细阈值,即当数据量已经小于这个阈值的时间举行盘算,否则举行fork 将使命分别成更小的数据块,举行求解。这里值得注意的是,getTargetSize 在第一次调用的时间会设置:
推测数据量巨细 / (默认并发度 * 4) 的结果作为最小实行单元的数量(设置的默认值是cpu 数 – 1,可以通过java.util.concurrent.ForkJoinPool.common.parallelism设置)
其他阐明
Optional操纵
通常聚合操纵会返回一个Optional范例,Optional表现一个安全的指定结果范例,所谓的安全指的是制止直接调用返回范例的null值而造成空指针非常,调用optional.ifPresent()可以判定返回值是否为空,大概直接调用ifPresent(Consumer super T> consumer)在结果部位空时举行消耗操纵;调用optional.get()获取返回值。
!