Java8新特性
- 速度更快:如HashMap底层使用红黑树
- 代码更少
- 强大的Stream API
- 便于并行
- 最大化减少空指针异常:Optional
Nashorn
引擎:在JVM上运行JS应用
1 Lambda表达式
1.1 Lambda表达式的格式
(o1, o2) -> Integer.compare(o1, o2)
- ->:
lambda操作符
或者箭头操作符
- 左边:
lambda形参列表
,也即是接口中抽象方法的形参列表 - 右边:
lambda体
,重写的抽象方法的方法体 - Lambda表达式的本质是作为接口的实例
1.2 为什么使用Lambda表达式
- Lambda表达式是一个
匿名函数
,可以理解为一段可以传递的代码(将代码像数据一样进行传递) - 可以写出更简洁、更灵活的代码
- Lambda表达式只能用于只含有一个抽象方法的、并且被
@FunctionalInterface
标识的接口 ->
即为Lambda操作符
或者箭头操作符
- :: 为方法引用
public static void main(String[] args) {
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("111");
}
};
runnable1.run();
Runnable runnable2 = () -> {
System.out.println("222");
};
runnable2.run();
Comparator<Integer> comparator1 = new Comparator<>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
};
System.out.println(comparator1.compare(1, 2));
Comparator<Integer> comparator2 = (o1, o2) -> Integer.compare(o1, o2);
System.out.println(comparator2.compare(2, 1));
Comparator<Integer> comparator3 = Integer::compare;
System.out.println(comparator3.compare(1, 1));
}
1.3 Lambda的使用
总结:
- ->左边的
Lambda形参列表
:- Lambda形参列表的参数类型都可以省略(类型推断)
- 如果只有一个参数则可以省略小括号
- ->右边的
Lambda体
:- 如果只有一条执行语句,则可以省略大括号,如果有返回值,return关键字需要省略
情况举例:
-
1 无参、无返回值:
Runnable runnable2 = () -> { System.out.println("222"); }; runnable2.run();
-
2 需要参数,但无返回值:
Consumer<String> consumer = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } }; consumer.accept("123"); Consumer<String> consumer1 = (String s) -> { System.out.println(s); }; consumer1.accept("123");
-
3 数据类型可以省略,因为编译器可以推断得出,称为
类型推断
,像使用泛型创建对象的时候就不必写后面的类型,也是一种编译时的类型推断Consumer<String> consumer1 = (s) -> { System.out.println(s); }; consumer1.accept("123");
-
4 Lambda若只需要一个参数,则参数的小括号可以省略
Consumer<String> consumer1 = s -> { System.out.println(s); }; consumer1.accept("123");
-
5 Lambda需要两个或者两个以上的参数,且可以有返回值
Comparator<Integer> comparator2 = (o1, o2) -> { return Integer.compare(o1, o2); };
-
6 如果语句只有一条,则大括号可以省略,且带返回值的return可以省略
Comparator<Integer> comparator2 = (o1, o2) -> Integer.compare(o1, o2); System.out.println(comparator2.compare(2, 1));
2 函数式接口
-
Lambda在使用的时候,准确来说是作为
函数式接口
的实例存在 -
如果接口中只声明了一个抽象方法,则这个接口就是
函数式接口
-
@FunctinalInterface
仅仅起到一个标识检查的作用,检查标识的接口是否满足函数式接口的定义@FunctionalInterface public interface MyFunctionalInterface { void method1(); //void method2(); }
-
以前使用匿名实现类表示的,现在都可以使用Lambda表达式来写
2.1 Java内置的四大核心函数式接口
出现这四种接口,均可以使用Lambda表达式进行接口实例化
-
消费型接口 Consumer<T>
:void accept(T t),有参数无返回值public class LambdaTest2 { @Test public void test() { happyTime(500, money -> System.out.println("消费" + 500)); happyTime(500, System.out::println); } public void happyTime(double money, Consumer<Double> consumer) { consumer.accept(money); } }
-
供给型接口 Supplier
:T get(),无参数有返回值 -
函数型接口 Funcational<R, T>
:R apply(T t),有参数有返回值 -
断定型接口 Predicate<T>
:boolean test(T t),有参数,有返回值且为boolean@Test public void test() { //happyTime(500, money -> System.out.println("消费" + 500)); List<String> list = Arrays.asList("北京", "南京", "天津"); List<String> strings = filterString(list, str -> str.contains("京")); System.out.println(strings); } public List<String> filterString(List<String> list, Predicate<String> predicate) { List<String> filterStringList = new ArrayList<>(); for(String str : list) { if(predicate.test(str)) { filterStringList.add(str); } } return filterStringList; }
2.2 其他接口
3 方法引用
-
当要传递给Lambda体的操作,已经有相同的实现方法的时候,就可以使用方法引用
相同的实现方法要求实现接口的抽象方法的参数列表和返回值类型必须和参数引用的一致
-
方法引用就是一个lambda表达式,也就是函数接口的一个实例
-
就是通过方法的名字指向一个方法,可以认为是Lambda的一个语法糖
-
具体分为下面三种情况:
- 对象 :: 非静态方法
- 类 :: 静态方法
- 类 :: 非静态方法
类 :: 静态方法
@Test
public void test1() {
Consumer<String> consumer = str -> System.out.println(str);
consumer.accept("Hello");
Consumer<String> consumer1 = System.out::println;
consumer.accept("World!");
}
如Consumer的
参数列表
和返回值类型
和方法引用System.out::println
的相同,因此可以直接使用方法引用进行替换。
对象 :: 非静态方法
@Test
public void test2() {
Employee employee = new Employee(1001L, "Tom", 5600.0);
//Supplier<String> supplier = () -> employee.getName();
Supplier<String> supplier = employee::getName;
System.out.println(supplier.get());
}
4 构造器引用
-
和方法引用类似
-
无参构造器对应
supplier供给型接口
T get()@Test public void test() { Supplier<Employee> sup = new Supplier<Employee>() { @Override public Employee get() { return new Employee(); } }; System.out.println(sup.get()); Supplier<Employee> sup1 = Employee::new; System.out.println(sup1.get()); }
-
有参构造器对应
Function函数型接口
R apply(T t),如果有两个参数则使用BiFunction
R apply(T t, S s)@Test public void testAllConstruct() { Function<String, Employee> fun = Employee::new; System.out.println(fun.apply("zhang san")); } @Test public void testBiAllConstructor() { BiFunction<String, Integer, Employee> fun = Employee::new; System.out.println(fun.apply("zhangsan", 18)); }
5 数组引用
@Test
public void testArrayRef() {
Function<Integer, String[]> fun = new Function<Integer, String[]>() {
@Override
public String[] apply(Integer integer) {
return new String[integer];
}
} ;
System.out.println(Arrays.toString(fun.apply(10)));
Function<Integer, String[]> fun2 = String[]::new;
System.out.println(Arrays.toString(fun2.apply(10)));
}
标签:JDK,System,接口,JDK8,版本,println,Lambda,public,out
From: https://www.cnblogs.com/tod4/p/17910955.html