总结java8相关知识点
Java8新特性介绍
接口默认方法
lambda表达式
带有parameters和body的匿名函数,body可以是表达式或者代码块。
@FunctionalInterface函数式接口
自定义函数式接口示例
函数式接口注解@FunctionalInterface的定义:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
函数式接口就是普通的接口,但是有以下几个特点:
- 该接口有且只有一个抽象方法(默认方法,静态方法,override Object基类的方法,都不算是抽象方法)
- 加上@FunctionInterface注解只是为了编译器可以检查一个接口是否符合函数式接口的规范,这个注解不是必须的,如果符合规范,不加这个注解也同样是函数式接口(Callable、Runnable、Comparator等在java8中都加了这个注解)
示例:
@FunctionalInterface
public interface TestInterface {
// 只有一个抽象方法
void testMethod(String testParam);
// java.lang.Object中的方法不是抽象方法
@Override
boolean equals(Object var1);
@Override
String toString();
// default不是抽象方法
default void defaultMethod(){
System.out.println("this is default method");
}
default void defaultMethod2(){
System.out.println("this is default method2");
}
// static不是抽象方法
static void staticMethod(){
System.out.println("this is static method");
}
}
//带泛型和返回值的函数式接口
@FunctionalInterface
public interface Converter<F, T> {
T convert(F from);
}
//测试
public class Test {
public static void main(String[] args) {
//下面两种方式的效果是一样的,一个使用匿名内部类,一个使用lambda表达式
/*TestInterface testInterface = new TestInterface() {
@Override
public void testMethod(String testParam) {
System.out.println("this is test method, param: "+testParam);
}
};*/
TestInterface testInterface = (testParam)->{
System.out.println("this is test method, param: "+testParam);
};
testInterface.testMethod("zhangsan");
testInterface.defaultMethod();
testInterface.defaultMethod2();
//测试带泛型和返回值的函数式接口
Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted);
}
}
函数式接口可以结合lambda表达式,简化代码量,增加可读性,例如针对Runnable接口,以下两种使用方式效果是一样的:
new Thread(()->{
System.out.println("do something in Runnable");
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("do something in Runnable");
}
}).start();
内置函数式接口
- Predicate谓词型(判断是否正确)
//使用方式1: 直接实现接口
Predicate<Integer> predicate1 = new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
if(integer > 0){
return true;
}
return false;
}
};
System.out.println(predicate1.test(1));
//使用方式2: 使用lambda表达式
Predicate<Integer> predicate2 = (t) -> t > 0;
System.out.println(predicate2.test(-1));
//Stream.filter方法接收一个Predicate<? super T> predicate参数,比较常用
List<Integer> list = Arrays.asList(-1,0,1);
List<Integer> result = list.stream().filter(i->i>0).collect(Collectors.toList());
result.forEach(System.out::println);
- Function功能型(有出有入)
//使用方式1: 直接实现接口
Function<String,Integer> calcStringLength1 = new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return s.length();
}
};
System.out.println(calcStringLength1.apply("zhangsan"));
//使用方式2: 使用lambda表达式
Function<String,Integer> calcStringLength2 = s->s.length();
System.out.println(calcStringLength2.apply("zhangsan"));
//Stream.map方法接收一个Function<? super T, ? extends R>参数,比较常用
List<String> list = Arrays.asList("abc","a","abcdefg");
List<Integer> result = list.stream().map(s->s.length()).collect(Collectors.toList());
result.forEach(System.out::println);
- Supplier生产型(只有出)
//使用方式1: 直接实现接口
Supplier<Integer> supplier1 = new Supplier<Integer>() {
@Override
public Integer get() {
//返回一个随机值
return new Random().nextInt();
}
};
System.out.println(supplier1.get());
//使用方式2: 使用lambda表达式,
Supplier<Integer> supplier2 = () -> new Random().nextInt();
System.out.println(supplier2.get());
//使用方式3: 使用方法引用
Supplier<Double> supplier3 = Math::random;
System.out.println(supplier3.get());
- Consumer消费型(只有入)
//Iterable.forEach方法接收一个Consumer<? super T>参数
List<String> list = Arrays.asList("aaa","bbb","ccc");
//使用方式1: 直接实现接口方法
Consumer<String> consumer1 = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
list.forEach(consumer1);
//使用方式2: 使用lambda表达式
Consumer<String> consumer2 = (s) -> System.out.println(s);
list.forEach(consumer2);
//list.forEach((s) -> System.out.println(s));
//使用方式3: 方法引用
Consumer consumer3 = System.out::println;
list.forEach(consumer3);
//list.forEach(System.out::println);
::
操作符是lambda表达式的特殊写法,简化函数式接口的实现,但是方法的参数和返回值必须和函数式接口相同
函数式编程
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* 测试函数式编程
*/
public class FunctionalProgrammingTest{
public static void main(String[] args) {
NumberFunctions.of(10).add(30).subtraction(2).filter(number -> number>20).get().operate(System.out::println);
}
}
/**
* 定义函数式编程类
*/
class NumberFunctions {
private Integer number;
private NumberFunctions() {
}
private static NumberFunctions numberFunctions = new NumberFunctions();
public static NumberFunctions of(Integer number) {
numberFunctions.number = number;
return numberFunctions;
}
public NumberFunctions add(Integer number) {
numberFunctions.number += number;
return numberFunctions;
}
public NumberFunctions subtraction(Integer number) {
numberFunctions.number -= number;
return numberFunctions;
}
public Optional<NumberFunctions> filter(Predicate<Integer> predicate) {
if (predicate.test(this.number)) {
return Optional.of(numberFunctions);
}
return Optional.ofNullable(new NumberFunctions());
}
public void operate(Consumer<Integer> consumer) {
consumer.accept(this.number);
}
}
StreamApi
Stream.of(15, 26, 34, 455, 5, 6).map(number -> number * 2).sorted((num1, num2) -> num2 - num1).filter(integer -> integer % 4 == 0).collect(toList()).forEach(System.out::println);
::
操作符是lambda表达式的特殊写法,简化函数式接口的实现,但是方法的参数和返回值必须和函数式接口相同
CompletableFuture
https://qigangzhong.github.io/2019/06/03/Future-CompletableFuture/#%E4%BA%8Ccompletablefuture