目录
流Stream
Java8的集合支持新的stream方法会返回流(java.util.stream.Stream),流只能遍历一次;其可以支持常用的类似数据库的流操作。中间操作可以连接起来(将一个流转换为另一个流)构建一个流水线,终端操作会消耗流,以产生一个最终结果:
-
中间操作(返回Stream)
-
filter(Predicate<?>):返回匹配的流;
-
map(Function<? super T, ?extends R>):映射,返回应用map后的流;
-
limit(long maxSize):返回不超过maxSize数量元素的流;
-
sorted(Comparator<? super T>):排序;
-
disctinct():去重;
-
skip(n):跳过n个元素;
-
flatMap(Function<? super T, ? extends Stream<? extends R>>):流扁平化,把多个流合并为一个流;
-
-
数值映射:
-
映射到数值流:mapToInt, mapToDouble, mapToLong,特化后避免调用时装箱拆箱处理;
-
转回对象流:boxed,如把int转回为Integer
-
-
终端操作(只有调用终端时,所有流操作才真正执行):
-
void forEach(Consumer<? super T>):对每个元素执行Consumer;
-
long count():返回元素数;
-
collect(Collector<? super T>):返回集合,如collect(Collectoor.toList());
-
元素操作(返回Optional<T>):ifPrecent()可以在Optional有值时执行
-
findAny():返回某个元素;
-
findFirst():返回第一个元素,流为空时返回空;
-
max(Comparator<? super T>):返回最大元素;
-
min(Comparator<? super T>):返回最小元素;
-
-
匹配操作:
-
allMatch:全部匹配;
-
anyMatch:任一匹配;
-
noneMatch:无匹配;
-
-
归约操作:
-
T reduce(T init, BinaryOperator<T> accumulatro):对每个元素归约,如求和reduce(0, Integer::sum),
-
-
收集器Collectors类中的静态方法:
-
toList
-
toSet:生成set(删除重复项)
-
toCollection:指定集合,如collect(toCollection(), ArrayList::new);
-
counting:计算元素的个数,collect(counting());
-
summingInt:求和
-
averagingInt:求平均数;
-
summarizingInt:获取统计值(最大、最小、总和、平均值等);
-
joining:对流中每个元素的调用toString后连接成字符串,如collect(joining(", "));
-
maxBy, minBy
-
reducing:归约操作;
-
collectingAndThen:包裹另一个收集器,并对结果应用转换函数,如collect(collectingAndThen(toList(), List::size));
-
groupingBy:分组
-
partitioningBy:分区(分成true与false两组);
获取菜单(集合)中3条菜肴名称,并连接为一个字符串
String names = menu.stream()
.map(Dish::getName)
.limit(3)
.collect(Collectors.joining("; "));
获取包含的字符(去重后字符列表)
words = ["Hello", "World"]
words.stream()
.map(wd -> wd.split(""))
.flatMap(Arrays::stream)
.disctinct()
.collect(Collectors.toList());
构建流:
生成数值流:IntStream, LongStream,IntStream.rangeClosed(1, 100):[1,100]间数字组成的流;
Strean.of(...):显示构建流;
Arrays.Stream:由数组构建流;
由文件构建流:Files中很多静态方法会返回流;
由函数构建流:Stream.iterate, Stream.generate;
IntSupplier fib = new IntSupplier(){
int pre = 0;
int cur = 1;
public int getAsInt(){
int old = pre;
int next = pre+cur;
pre = cur;
cur = next;
return old;
}
}
IntStream.generate(fib).limit(10).forEach(System.out::println);
并行数据处理
要并行处理数据,可以通过对源调用parallelStream方法把集合转换为并行流,或调用parallel()方法把顺序流转换为并行流(sequential在转换为顺序流):
stream.parallel().
.filter(...)
.sequential()
.map(...)
.parallel()
.reduce()
要高效处理数据,需要:
-
留意装箱:自动装箱与拆箱会大大降低性能;Java8中的(IntStream, LongStream, DoubleStream)可避免此操作,尽量使用之;
-
有些操作在并行流上就是比顺序流上性能差:特别是limit、findFirst等依赖元素顺序的。
-
要考虑流的操作流水线的总计算成本;
-
对于较小的数据量,并行几乎从来都不是一个好的决定;
-
考虑流背后的数据结构是否易于分解:如ArrayList比LinkedList易于拆分;数据源与可分解性:
-
ArrayList:极佳;
-
LinkedList:差;
-
IntStream.range:极佳;
-
Stream.iterate:差;
-
HashSet:好;
-
TreeSet:好;
-
Optional<T>
Java8中引入java.util.Optional<T>用于存在或缺失变量的建模;可以明确表明可否为空(不存在)。
创建Optional对象:
-
Optional.empty():声明空的Optional;
-
Optional.of(inst):非空(包含对应值的),若inst为null,则抛出NullPointerException;
-
Optional.ofNullable(inst):创建允许null值的,若inst为null,则创建空的;
从Optional中读取实例的变量值:
-
get():存在则返回变量值,否则抛出NoSuchElementException异常;
-
orElse(T other):存在则返回变量值,否则返回默认值(other);
-
orElseGet(Supplier<? extends T> other):orElse延迟调用版,只有在对象不存在时,才会调用Supplier(可能是耗时操作);
-
orElseThrow(Supplier<? extends X> exceptionSupplier):与get类似,但是抛出指定的异常;
-
ifPresent(Consumer<? super T>):存在则返回变量值,否则无任何操作;
其他类方法:
-
filter:值存在且满足过滤条件则返回包含值的Optional对象,否则返回空Optional;
-
flatMap:若值存在执行提供的mapping函数,返回一个Optional类型的值,否则返回空Optional;
-
map:若值存在执行提供的mapping函数;
-
isPresent:值存在返回true,否则返回false;
多个Optional的链式操作(getCar返回Optional<Car>,getName直接返回String),通过flatMap避免Optional的嵌套(Optional<Optional<T>>):
Optional<Person> person=...;
String name = person.filter(p -> p.getAge() > 20)
.flatMap(Person::getCar)
.map(Car::getName)
.orElse("Unkown");
Java 8 Stream API与Optional详解
本文深入探讨Java 8中的Stream API,包括构造流、中间操作、终端操作及并行数据处理策略。同时,解析了Optional类的使用方法,以避免空指针异常,提升代码质量。
6074

被折叠的 条评论
为什么被折叠?



