optional转化为set_JDK8新特性--学习笔记(Optional&Collectors)

Optional

为什么要用Optional为了避免空对象的出现,这是大家都知道的基础事实

Optional是函数交互的时候,不管是传参还是返回值,封装的Optional都能很好的规避null的情况。(尤其重要!!!)

当你看到Optional类的时候,实际上你就得到了一个警示,该对象可能不存在,需要isPresent()的判断。

当你使用较长的调用链,如A.getX().getY().getZ(),每一步都有可能NPE,而封装Optional再调用就会自动保护null情况。flyhero:为什么我要使用Optional ?​zhuanlan.zhihu.com

Optional方法

构造方法

//返回空的 Optional 实例。static Optional empty()

//返回一个指定非null值的Optional。static Optional of(T value)

//如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。static Optional ofNullable(T value)

获取Optinal中内容方法

map方法返回成员变量,避免嵌套空指针,返回值同样用Optional包装,如果返回值是Option则会出现Option>,此时就需要使用flatmap。

一般不会在这里使用mapper做过多操作,业务逻辑应该放在get方法之后。

//如果有值,则对其执行调用映射函数得到返回值的Optional,否则返回空OptionalOptional map(Function super T,? extends U> mapper)

//使用示例Optionalperson = Optional.of(new Person());

person.map(Person::getCar)

get方法要求Optional内值不为null,所以需要进行isPresent()判断

//如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementExceptionT get()

//使用示例 Optional userOp = getUser(110L);

if (userOp.isPresent()){

User user = userOp.get();

// TODO }

flatmap方法如果mapper方法的返回值是Optional的话,就需要使用flatmap以避免出现Option>

flatmap规定mapper方法的返回值一定是Option类型

//如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional Optional flatMap(Function super T,Optional> mapper)

Optinal中内容为null处理方法

Supplier是参数无返回T的函数式接口,通常会在这里使用XXX::new方法引用,用来创建默认对象

//如果存在该值,返回值, 否则返回 other。T orElse(T other)

//如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。T orElseGet(Supplier extends T> other)

Optinal判断方法

//如果值存在则方法会返回true,否则返回 false。boolean isPresent()

//如果值存在则使用该值调用 consumer , 否则不做任何事情。void ifPresent(Consumer super T> consumer)

//示例//常用输出打印Optional.ifPresent(System.out::println)

Collectors工具类

什么是Collectors

Java 8中有一个Collector接口,主要是为Stream中的元素转换成其他值提供的一个接口,而在Collectors工具类中有很多Collector接口的实现方式。

其主要功能如下Reducing and summarizing stream elements to a single value

group elements

partition elements

Collectors常用方法

Reducing and summarizing stream elements to a single value

toXXX()类型转换

toList文档中描述对返回的List的类型,可变性,可串行化性或线程安全性没有保证,只能用List去接收返回值。如果要返回特定实现,可以改用Collectors#toCollection(Supplier)

所以用toCollection,要啥就new啥

要注意以下情况会报错

/** 因为Arrays.stream()是转成IntStream,基本数据类型无法转成collection类型,必须加boxed()* 将它转为Stream才可以继续转*/

int[] A = new int[]{1,2,3,4};

Arrays.stream(A).boxed().collect(Collectors.toCollection(LinkedList::new));//正确Arrays.stream(A).collect(Collectors.toCollection(LinkedList::new));//错误

Collector toCollection(Supplier collectionFactory)

//示例tasks.stream().collect(Collectors.toCollection(LinkedHashSet::new))keyMapper: 该Funtion用来生成Key

valueMapper:该Funtion用来生成value

mergeFunction:解决同一个key冲突的规则

mapSupplier:使用任何其它的Map实现,否则默认是Map类型

toMap(Function super T, ? extends K> keyMapper,

Function super T, ? extends U> valueMapper,

BinaryOperator mergeFunction,

Supplier mapSupplier)

//示例tasks.stream().collect(toMap(Task::getTitle, identity(), (t1, t2) -> t2, LinkedHashMap::new));

使用collect可以将Stream转换成值。maxBy和minBy允许用户按照某个特定的顺序生成一个值。

聚合操作

averagingDouble:求平均值,Stream的元素类型为double

averagingInt:求平均值,Stream的元素类型为int

averagingLong:求平均值,Stream的元素类型为long

counting:Stream的元素个数

maxBy:在指定条件下的,Stream的最大元素

minBy:在指定条件下的,Stream的最小元素

reducing: reduce操作

summarizingDouble:统计Stream的数据(double)状态,其中包括count,min,max,sum和平均。

summarizingInt:统计Stream的数据(int)状态,其中包括count,min,max,sum和平均。

summarizingLong:统计Stream的数据(long)状态,其中包括count,min,max,sum和平均。

summingDouble:求和,Stream的元素类型为double

summingInt:求和,Stream的元素类型为int

summingLong:求和,Stream的元素类型为long

group elements

groupby方法

classifier:分组依据,根据返回值进行分组,即分组的key决定函数

mapFactory: 返回的map类型,如TreeMap::new

downstream:我们可以先将classifier作为key进行分组,然后将分组后的结果交给downstream收集器再进行处理,必须还是Collector的方法

groupingBy(Function super T, ? extends K> classifier,

Supplier mapFactory,

Collector super T, A, D> downstream

//示例Map> namesByCity

= people.stream().collect(groupingBy(Person::getCity, TreeMap::new,

mapping(Person::getLastName, toSet())));

partitioningBy方法

它只能接受Predicate对象,将数据分为true和false的两个部分(还不如用groupby)

predicate:断言函数,参数T返回boolean,根据true/false分组

downstream:我们可以先将classifier作为key进行分组,然后将分组后的结果交给downstream收集器再进行处理,必须还是Collector的方法

partitioningBy(Predicate super T> predicate,Collector super T, A, D> downstream)

//示例Map partiCount = Stream.of(1, 2, 3, 4)

.collect(Collectors.partitioningBy(it -> it.intValue() % 2 == 0,

Collectors.counting()));

Collector接口原理

这个一定要清楚:Collector, 其中泛型参数T表示Stream中元素的类型,A表示定义一个初始容器的类型,R表示最终转换的类型。

Collector接口主要定义了如下几个方法:supplier:这个方法主要是生成一个初始容器,用于存放转换的数据。它返回一个Supplier类型,用Lambda表示为() -> A

accumulator:这个方法是将初始容器与Stream中的每个元素进行计算,它返回一个BiConsumer类型,用Lambda表示为(A, T) -> void

combiner: 这个方法用于在并发Stream中,将多个容器组合成一个容器,它返回一个BinaryOperator类型,用Lambda表示为(A, A) -> A

finisher:这个方法用于将初始容器转换成最终的值,它返回一个Function类型,用Lambda表示为A -> R

characteristics:这个方法返回该Collector具有的哪些特征,返回的是一个Set, 分别是CONCURRENT(并发), UNORDERED(未排序),IDENTITY_FINISH(finisher方法直接返回初始容器)等特征的组合

public class JoinCollector implements Collector {

@Override

public Supplier supplier() {

return StringBuilder::new;

}

@Override

public BiConsumer accumulator() {

return StringBuilder::append;

}

@Override

public BinaryOperator combiner() {

return StringBuilder::append;

}

@Override

public Function finisher() {

return StringBuilder::toString;

}

@Override

public Set characteristics() {

//EnumSet.of(Collector.Characteristics.IDENTITY_FINISH),如果要自己增加定义的话 return Collections.emptySet();

}

}

自定义实现的joining方法

// 输出 abcdSystem.out.println(Stream.of("a", "b", "c", "d").collect(new JoinCollector()));

引用和资料来源Collector讲解​www.cnblogs.com自定义Collector示例​irusist.github.ioCSDN-专业IT技术社区-登录​blog.csdn.net【译】java8之collector​www.jianshu.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值