Lambda表达式

Lambda 是一个匿名函数,可以理解为一段可以传递的代码,写出更简洁、更灵活的代码。
组成:
Java8中引入了一个新的操作符号 “->”,称为lambda操作符
左侧:表达式的参数列表
右侧:表达式的执行功能

语法格式一: 无参数,无返回值

	() -> System.out.println(“hello world”);

语法格式二: 有一个参数,无返回值

	() -> System.out.println(x)

语法格式三 : 若只有一个参数,小括号可以省略不写

	x -> System.out.println(x)

语法格式四 : 有两个以上的参数,有返回值,并且 Lambda 体中有多条语句

	Comparator<Integer> com = (x, y) -> {
	    System.out.println("函数式接口");
	    return Integer.compare(x, y);
	};

语法格式五 : 若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写

	Comparator<Integer> com = (x, y) -> Integer.compare(x, y);

语法格式六 : Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”

	(Integer x, Integer y) -> Integer.compare(x, y);

Lambda表达式的参数类型都是由编译器推断得出,表达式中不需要指定类型,程序依然可以编译,因为javac根据程序的上下文在后台推断出了参数的类型。这就是“类型推断”。

Collectors 实现了接口 Collector<T,A,R>
T: 需要进行reduce操作的元素类型
A:reduce操作的动态集合类型
R:reduce操作的结果类型

Function<T,R>
T—函数的输入类型
R-函数的输出类型

方法引用:
用来直接访问类或者实例的已经存在的方法或者构造方法。方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的目标类型上下文。计算时,方法引用会创建函数式接口的一个实例。
函数式接口:
函数式接口是只包含一个抽象方法的接口。函数式接口有时候被称为SAM类型,意思是单抽象方法(Single Abstract Method)
一般来说,这个抽象方法指明了接口的目标用途。因此,函数式接口通常表示单个动作。
此外,函数式接口定义了lambda表达式的目标类型。但lambda表达式只能用于其目标类型已经被指定的上下文中。
同时,Java 8引入了一个新的注解:@FunctionalInterface。
可以在任意函数式接口上面使用 @FunctionalInterface 来标识它是一个函数式接口,但是该注解不是强制的。
函数式接口可以定义Object定义的任何公有方法,例如equals(),而不影响其作为函数式接口的状态。Object的公有方法被视为函数式接口的隐式成员,因为函数式接口的实例会默认自动实现它们。
默认方法和静态方法不会违反函数接口。
Lambda表达式本质就是一个匿名(未命名的方法)。这个方法不能独立执行,而是用于实现由函数式接口定义的一个方法(使用Lambda表达式实例化函数式接口)。因此,lambda表达式会导致产生一个匿名类。
Lambda表达式不是独立执行的,而是构成了一个函数式接口定义的抽象方法的实现,该函数式接口定义了它的目标。结果,只有在定义了Lambda表达式的目标类型的上下文中,才能使用该表达式。当把一个Lambda表达式赋给一个函数式接口的引用时,就创建了这样的上下文。
当目标类型上下文中出现Lambda表达式时,就会自动创建实现了函数式接口的一个类的实例(类似于匿名类),函数式接口声明的抽象方法的行为由Lambda表达式定义。当通过目标调用该方法时,就会执行Lambda表达式。
为了在目标类型上下文中使用lambda表达式,抽象方法的类型和lambda表达式的类型必须兼容。eg:如果抽象方法指定了两个int类型的参数,那么lambda表达式也必须执行两个参数,其类型要么被显示指定为int类型,要么在上下文中可以被隐式的推断为int类型。总的来讲,lambda表达式的参数的类型和数量必须与函数式接口内的抽象方法的参数兼容;返回类型必须兼容;并且lambda表达式可能抛出的异常必须能被该方法接受。

Optional

直白的讲, 当我们还在以如下几种方式使用 Optional 时, 就得开始检视自己了
调用 isPresent() 方法时
调用 get() 方法时
Optional 类型作为类/实例属性时
Optional 类型作为方法参数时
isPresent() 与 obj != null 无任何分别, 我们的生活依然在步步惊心. 而没有 isPresent() 作铺垫的 get() 调用在 IntelliJ IDEA 中会收到告警
Reports calls to java.util.Optional.get() without first checking with a isPresent() call if a value is available. If the Optional does not contain a value, get() will throw an exception. (调用 Optional.get() 前不事先用 isPresent() 检查值是否可用. 假如 Optional 不包含一个值, get() 将会抛出一个异常)
把 Optional 类型用作属性或是方法参数在 IntelliJ IDEA 中更是强力不推荐的
Reports any uses of java.util.Optional, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong or com.google.common.base.Optional as the type for a field or a parameter. Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result”. Using a field with type java.util.Optional is also problematic if the class needs to be Serializable, which java.util.Optional is not. (使用任何像 Optional 的类型作为字段或方法参数都是不可取的. Optional 只设计为类库方法的, 可明确表示可能无值情况下的返回类型. Optional 类型不可被序列化, 用作字段类型会出问题的)
所以 Optional 中我们真正可依赖的应该是除了 isPresent() 和 get() 的其他方法:
public Optional map(Function<? super T, ? extends U> mapper)
public T orElse(T other)
public T orElseGet(Supplier<? extends T> other)
public void ifPresent(Consumer<? super T> consumer)
public Optional filter(Predicate<? super T> predicate)
public Optional flatMap(Function<? super T, Optional> mapper)
public T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

又不得不提一下 Optional 的三种构造方式: Optional.of(obj) , Optional.ofNullable(obj) 和明确的 Optional.empty()
Optional.of(obj) : 它要求传入的 obj 不能是 null 值的, 否则还没开始进入角色就倒在了 NullPointerException 异常上了.
Optional.ofNullable(obj) : 它以一种智能的, 宽容的方式来构造一个 Optional 实例. 来者不拒, 传 null 进到就得到 Optional.empty() , 非 null 就调用 Optional.of(obj) .
那是不是我们只要用 Optional.ofNullable(obj) 一劳永逸, 以不变应二变的方式来构造 Optional 实例就行了呢? 那也未必, 否则 Optional.of(obj) 何必如此暴露呢, 私有则可?

  1. 当我们非常非常的明确将要传给 Optional.of(obj) 的 obj 参数不可能为 null 时, 比如它是一个刚 new 出来的对象( Optional.of(new User(…)) ), 或者是一个非 null 常量时; 2. 当想为 obj 断言不为 null 时, 即我们想在万一 obj 为 null 立即报告 NullPointException 异常, 立即修改, 而不是隐藏空指针异常时, 我们就应该果断的用 Optional.of(obj) 来构造 Optional 实例, 而不让任何不可预计的 null 值有可乘之机隐身于 Optional 中.

Stream

Java 8函数式编程,通过流(Stream)API来支持对集合的filter、map、reduce操作,流是java8中处理集合的关键抽象概念,实现声明式的集合处理方式。

流和集合的区别:
无存储(no storage),流通过计算的操作流水线来传输数据源。数据源如数据结构、数组、生成器函数或I/O通道。
原生函数式,对流进行操作会产生结果,但并不会修改数据源。筛选流,是生成一个不包含被筛选掉的元素新流,而不是从源集合中删除元素。
惰性读取(laziness-seeking)。很多对流的操作,如筛选(filtering)、映射、去重(duplicate removal),能够被惰性实现,以便于性能的优化。如,“找出第一个由三个连续单词组成的String”,并不需要检测全部的输入字符串。流操作被划分为中间操作(用于生成流)和终止操作(用于生成值或副作用)。中间操作总是惰性的。
可能是无界的(possibly unbounded)。集合的大小是必须确定的,但流并不是。像limit(n) 或 findFirst()这样的逻辑短路操作,允许在有限时间内完成对无限流的计算。
可消耗的(consumable)。流的元素在流的生命周期中只能被访问一次。类似于 Iterator,要想重新访问同一个元素,必须生成新的流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值