jdk1.8新特性汇总如下图![jdk1.8特性图汇总](https://img-blog.csdnimg.cn/e3bcc028aae14bd9a827fa57cf797aed.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Yid55Sf54mb54qK5Li25rGf5rmW55u46KeB,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
核心/常用知识点
函数式编程(Lambda表达式)
特点
它不是一种具体的技术,是一种方法论,使用对应提供的函数进行编程,而不是去关心内部的实现。
使用格式
1·方法没有参数:()->{ }
2·方法有参数:(参数,参数)->{ }
3·如果现在只有一行语句返回:(参数,参数)->语句
内置函数接口
Consumer 函数式接口(消费型)
- 作用
接受单个输入参数并且不返回结果的操作,与大多数其他功能接口不同, Consumer预期通过副作用进行操作。 - 源码
下面展示一些内联代码片
。
/**
* 接受单个输入参数并且不返回结果的操作。
* 与大多数其他功能接口不同, Consumer预期通过副作用进行操作。
*
* @since 1.8
*/
@FunctionalInterface
public interface Consumer<T> {
/**
* 对给定的参数执行此操作。
*
* @param t the input argument
*/
void accept(T t);
/**
* 返回一个组合的Consumer ,依次执行此操作,然后执行after操作。
* 如果执行任一操作会抛出异常,它将被转发到组合操作的调用者。
* 如果执行此操作会引发异常,则不会执行after操作。
*
* @param 此操作后执行的操作
* @return 一个组成的 Consumer ,依次执行 after操作
* @throws NullPointerException - if after is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
- 示例代码
从上述示例可以看出,这个函数相当于预先给你一些默认的操作,如果只要传入相对应的参数进去就能自动帮你实现功能。/** * 获取一个新的字符串 * @param name * @param consumer */ public static void getNewStr(String name,Consumer<String> consumer){ consumer.accept(name); } public static void main(String[] args) { String name = "张三"; getNewStr(name,(x)-> System.out.println(x+"去吃饭了...")); //输出结果为:张三去吃饭了... }
Function 函数(转换型)
- 作用
Function接口 接受一个输入参数T,返回一个结果R。 - 源码
下面展示一些内联代码片
。
@FunctionalInterface
public interface Function<T, R> {
// 接受输入参数,对输入执行所需操作后 返回一个结果。
R apply(T t);
// 返回一个 先执行before函数对象apply方法,再执行当前函数对象apply方法的 函数对象。
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
// 返回一个 先执行当前函数对象apply方法, 再执行after函数对象apply方法的 函数对象。
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
// 返回一个执行了apply()方法之后只会返回输入参数的函数对象。
static <T> Function<T, T> identity() {
return t -> t;
}
}
- 示例代码
/**
* 获取一个新的价格
* @param price
* @param function
* @return
*/
static Double getNewPrice(Float price, Function<Float,Double> function){
return function.apply(price);
}
public static void main(String[] args) {
Double newPrice = getNewPrice(20.36F, (x) -> (double) x + 30);
System.out.println(newPrice);
//输出结果为:50.36000061035156
}
- 总结
从上面示例可以看出,function 提供的是一个转换型的功能,数据类型转换。 - andThen 使用
– 示例代码
/**
* 从参数可知,function 第一次已经将float转换成double了,第二次将double转换成float
* 本示例是告诉用法,不要以为是没事转换来转换去
* @param price
* @param function
* @param function2
* @return
*/
static Float getNewPrice(Float price, Function<Float,Double> function,Function<Double,Float> function2){
return function.andThen(function2).apply(price);
}
public static void main(String[] args) {
Float newPrice = getNewPrice(20.36F, (x) -> (double) x + 30,(x)->(float)(x + 20) );
System.out.println(newPrice);
}
Supplier 函数(供给型)
- 作用
获取一个结果 - 源码
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
- 示例代码
public static String getNewStr(Supplier<String> supplier){
return supplier.get();
}
public static void main(String[] args) {
String name = "张三";
String newStr = getNewStr(()->name+"去吃饭了...");
System.out.println(newStr);
//输出结果为:张三去吃饭了...
}
- 总结
supplier供给型明显和consumer消费型不相同,虽然输出结果都是一样,使用起来也不一样,supplier是有返回结果的,consumer 是没有返回结果的
Predicate 断言式 函数(判断型)
- 作用
- 源码
/**
* 执行返回结果
*/
boolean test(T t);
/**
* 多条件同时满足
*/
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
/**
* 执行结果的反转值
* true变成 false ,false 变成true
*/
default Predicate<T> negate() {
return (t) -> !test(t);
}
/**
* 两个条件或者
*/
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
/**
* 是否是同一对象
*/
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
- 示例代码
/**
* 获取断言信息
* @param value
* @param predicate
* @return
*/
public static Boolean getPredicate(Integer value, Predicate<Integer> predicate){
return predicate.test(value);
}
public static void main(String[] args) {
Integer math = 20 ;
Boolean predicate = getPredicate(math, (x) -> x >= 30);
System.out.println(predicate);
}
- 总结
用于校验条件是否满足情况。
Comparator排序
- 示例代码
public static void main(String[] args) {
List<Student> studentList = Arrays.asList(new Student("张三", 7, 90.00),
new Student("李四", 6, 80.05),
new Student("王五", 3, 100.00));
//多线程并发情况下能保证线程安全
Collections.synchronizedList(studentList)
//按成绩进行倒叙排列
Collections.sort(studentList,Comparator.comparing(Student::getGrade).reversed());
//遍历新的集合顺序
studentList.forEach(student->{
System.out.println(student.toString());
});
//输出结果为:
//王五年龄是 :3, 分数是:100.0分
//张三年龄是 :7, 分数是:90.0分
//李四年龄是 :6, 分数是:80.05分
}
@Data
@AllArgsConstructor
public static class Student{
private String name;
private Integer age;
private Double grade;
@Override
public String toString() {
return name + "年龄是 :" + age + ", 分数是:" + grade + '分';
}
}
易于并发编程 parallel()
比如在一堆数字中寻找最小值
当这堆数字很大的时候,我们需要去实现多线程去比较的话,需要考虑多线程,线程池以及拆分数据,实现快排等,但是当我们使用JDK8函数式编程的时候可以直接使用一个方法开启 并行 .parallel()
int min = IntStream.of(nums).parallel().min().getAsInt();
比较下函数式编程和命令式编程
- 函数式编程
int min = IntStream.of(nums).parallel().min().getAsInt();
- 命令式编程
int minNum = Integer.MAX_VALUE;
for (int num : nums) {
if (num < minNum) {
minNum = num;
}
}
通过上述函数式编程优势很明显,不需要处理内部是怎么实现的,只需要得到一个结果就行了。
Option类
作用
Optional 可以省去非空判断,因为内部已经实现了,避免了空指针异常。
常用方法
方法 | 描述 |
---|---|
of | 把指定的值封装为Optional对象,如果指定的值为null,则抛出NullPointerException |
empty | 创建一个空的Optional对象 |
ofNullable | 把指定的值封装为Optional对象,如果指定的值为null,则创建一个空的Optional对象 |
get | 如果创建的Optional中有值存在,则返回此值,否则抛出NoSuchElementException |
orElse | 如果创建的Optional中有值存在,则返回此值,否则返回一个默认值 |
orElseGet | 如果创建的Optional中有值存在,则返回此值,否则返回一个由Supplier接口生成的值 |
orElseThrow | 如果创建的Optional中有值存在,则返回此值,否则抛出一个由指定的Supplier接口生成的异常 |
filter | 如果创建的Optional中的值满足filter中的条件,则返回包含该值的Optional对象,否则返回一个空的Optional对象 |
map | 如果创建的Optional中的值存在,对该值执行提供的Function函数调用 |
flagMap | 如果创建的Optional中的值存在,就对该值执行提供的Function函数调用,返回一个Optional类型的值,否则就返回一个空的Optional对象 |
isPresent | 如果创建的Optional中的值存在,返回true,否则返回false |
ifPresent | 如果创建的Optional中的值存在,则执行该方法的调用,否则什么也不做 |
默认方法(@FunctionalInterface )
默认方法的作用
这个新特性其实是很重要的,它的作用就是在接口上可以定义方法的实现 作为默认方法,这样
Java就可以扩展很多底层接口 比如List接口 ,对其添加了很多default默认方法,这时候List的接口的实现类也不用去修改了。
特点
- 一个类实现多个接口,因此可以采用实现多个接口的方式实现多重继承的目的。
- 接口中成员的修饰符都是public或者default,不能使用private和protected修饰。
- 接口可以默认方法与静态方法,有方法体的实现。但abstract修饰的抽象方法没有方法体。
- 标识接口
Java语言中,有些接口内部没有声明任何方法,也就是实现这些接口不需要重写任何方法,这些没有任何方法声明的接口叫做标识接口。比如clonable和Serializable接口等,表示实现它的类属于一个特定的类型。
示例代码
@FunctionalInterface
interface Interface1 {
int doubleNumber(int i);
default void someMethod(){
System.out.println("Interface1 default Method ");
}
}
多重实现的默认方法冲突
@FunctionalInterface
interface Interface1 {
int doubleNumber(int i);
void someMethod();
}
类型注解(ElementType)
含义:在各种程序元素(定义类、定义接口、定义方法、定义成员变量…)
ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中。
ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中(eg:声明语句、泛型和强制转换语句中的类型)。
重复注解
含义
标注在类,方法等上面的注解可以重复出现,之前是不允许
添加了新的getAnnotationsByType()
getAnnotationsByType(),可以返回某个类型的重复注解,例如Filterable.class.getAnnoation(Filters.class)将返回两个Filter实例,输出到控制台的内容如下所示:
filter1
filter2