Java8新特性
主要内容
- Lamdba表达式
- 函数式接口
- 方法引用和构造器引用
- Stream API
- 接口中的默认方法与静态方法
- 新时间日期API
- 其他新特性
java8新特性介绍
- 速度更快(HashMap、元空间)
- 代码更少(Lambda表达式)
- 强大的Stream API(将java变成sql)
- 便于并行()
- 最大化减少空指针异常
Lamdba和Stream 为核心
一、Lambda表达式
为什么使用Lambda表达式
Lamdba是一个匿名函数,我们可以将Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。
Lambda表达式基础语法
java8引入新的操作符 “->” 该操作符称为箭头操作或Lambda操作符
箭头操作符将Lambda 拆分为两部分
左侧:Lambda 表达式的参数列表
右侧:Lambda 表达式所执行的功能,即Lambda体
Lambda六种基本格式
-
无参数、无返回值
()-> System.out.println(“Hello,Lambda”)
@Test public void test1(){ //JDK 1.7之前必须加final; 1.8后默认为final int num=0; Runnable runnable=new Runnable() { @Override public void run() { System.out.println("hello"+num); } }; runnable.run(); System.out.println("================"); /** ()-> System.out.println("Hello,Lambda") */ Runnable runnable1=()-> System.out.println("hello"+num); runnable1.run(); }
-
一个参数、无返回值
(s)->System.out.println(s)
@Test public void test2(){ Consumer<String> consumer=new Consumer<String>() { @Override public void accept(String s) { System.out.println("匿名内部类"+s); } }; Consumer<String> consumer1=(s)-> System.out.println("Lambda表达式 "+s); consumer1.accept("这是参数"); }
-
一个参数、无返回值;小括号可以省略
s->System.out.println(s)
@Test public void test2(){ Consumer<String> consumer=new Consumer<String>() { @Override public void accept(String s) { System.out.println("匿名内部类"+s); } }; Consumer<String> consumer1=(s)-> System.out.println("Lambda表达式 "+s); consumer1.accept("这是参数"); /** * 当参数为一个时,小括号可以省略 */ Consumer<String> consumer2=s-> System.out.println("Lambda表达式 "+s); consumer2.accept("小括号没了"); }
-
两个以上的参数、有返回值、并且Lambda 体中有多条语句
Comparator comparator=(x,y)->{
System.out.println(“函数式接口”);
return Integer.compare(x,y);
};@Test public void test3(){ Comparator<Integer> comparator=(x,y)->{ System.out.println("函数式接口"); return Integer.compare(x,y); }; }
-
若Lambda 体只有一条语句,return 和 大括号都可以省略不写
Comparator comparator1=(x,y)->Integer.compare(x,y);
@Test
public void test4(){
Comparator<Integer> comparator=(x,y)->Integer.compare(x,y);
}
6.Lambda表达式参数的数据类型可以省略不写,因为JVM可以通过上下文推断出类型即“类型推断”
@Test
public void test4(){
/**
* 数据类型可以省略
*/
Comparator<Integer> comparator=(Integer x,Integer y)->Integer.compare(x,y);
}
小结:左右遇一括号省,左侧推断类型省。
Lambda表达式需要函数式接口支持
函数式接口:接口中只有一个抽象方法的接口,可以使用@FunctionalInterface修饰,作用类似@Overweite。
简单的使用
自定义一个通用算法接口,求一个数的平方
@FunctionalInterface
public interface MyFun<T>{
public T getValue(T num);
}
package org.lfh.java8.mylambdaplus;
public class MyFunDemo {
public static void main(String[] args) {
/**
* 求一个数的平方
*/
Integer operation = operation(100, new MyFun<Integer>() {
@Override
public Integer getValue(Integer num) {
return num * num;
}
});
System.out.println("operation = " + operation);
/**
* Lambda表达式
*/
Integer operation1 = operation(100, x -> x * x);
System.out.println("Lambda表达式" + operation1);
}
public static Integer operation(Integer num,MyFun<Integer> myFun){
return myFun.getValue(num);
}
}
Lambda练习
-
调用Collections.sort()方法,通过定制排序比较俩个Employee(先按年龄比,年龄相同按姓名比),使用Lambda作为参数传递
package org.lfh.java8.lambdademo; import java.util.Objects; /** * @author lifh * @creat 2020/10/25/20:59 */ public class Employee { /** * 年龄 */ private Integer age; /** * 姓名 */ private String name; public Employee() { } public Employee(Integer age, String name) { this.age = age; this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Employee{" + "age=" + age + ", name='" + name + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Employee employee = (Employee) o; return Objects.equals(age, employee.age) && Objects.equals(name, employee.name); } @Override public int hashCode() { return Objects.hash(age, name); } }
package org.lfh.java8.lambdademo; /** * @author lifh * @creat 2020/10/25/21:00 */ import java.util.ArrayList; import java.util.Collections; /** * 调用Collections.sort()方法, * 通过定制排序比较俩个Employee(先按年龄比,年龄相同按姓名比), * 使用Lambda作为参数传递 * * @author lfh */ public class Demo { public static void main(String[] args) { Employee employee1 = new Employee(18, "李四"); Employee employee = new Employee(18, "张三"); Employee employee2 = new Employee(16, "张三"); ArrayList<Employee> arrayList = new ArrayList<>(); arrayList.add(employee); arrayList.add(employee1); arrayList.add(employee2); Collections.sort(arrayList, (e1, e2) -> { if (e1.getAge() - e2.getAge() == 0) { return e1.getName().compareTo(e2.getName()); } else { return Integer.compare(e1.getAge(), e2.getAge()); } }); System.out.println("arrayList = " + arrayList); } }
-
声明函数式接口,接口中声明抽象方法,Public String getValue(Sting str);
package org.lfh.java8.lambdademo; /** * @author lifh * @creat 2020/10/25/21:14 */ @FunctionalInterface public interface MyFun { /** * @param str * @return */ public String getValue(String str); }
-
声明类TestLambda,类中编写方法使用接口作为参数,将一个字符串转化为大写,并作为方法的返回值
package org.lfh.java8.lambdademo; /** * @author lifh * @creat 2020/10/25/21:16 */ public class TestLambda { public static void main(String[] args) { String abc = getBigValue("abc", x -> x.toUpperCase()); System.out.println("abc = " + abc); } /** * 接口作为参数,将一个字符串转化为大写,并作为方法的返回值 */ public static String getBigValue(String str,MyFun myFun){ return myFun.getValue(str); } }
-
再将一个字符串的第二个和第四个索引进行截取字符串
/**
* 将一个字符串的第二个和第四个索引进行截取字符串
*/
String subStr = getBigValue("我是吴彦祖", x -> x.substring(2, 5));
System.out.println("截取后 = " + subStr);
-
声明一个带两个泛型参数的函数式接口,泛型类型为<T,R>,T为参数,R为返回值。
package org.lfh.java8.lambdademo; /** * @author lifh * @creat 2020/10/25/21:27 */ public interface MyFunction2<T,R> { /** * 获取值 * @param t1 * @param t2 * @return */ public R getValue(T t1,T t2); }
-
接口声明对应的抽象方法
-
在TestLambda类中声明方法,使用接口作为参数,计算两个long类参数的和。
-
package org.lfh.java8.lambdademo; /** * @author lifh * @creat 2020/10/25/21:16 */ public class TestLambda { public static void main(String[] args) { /** * 接口作为参数,将一个字符串转化为大写,并作为方法的返回值 */ String abc = getBigValue("abc", x -> x.toUpperCase()); System.out.println("abc = " + abc); /** * 将一个字符串的第二个和第四个索引进行截取字符串 */ String subStr = getBigValue("我是吴彦祖", x -> x.substring(2, 5)); System.out.println("截取后 = " + subStr); /** * 计算两个long类参数的和 */ longT(100L,200L,(e1,e2)->e1+e2); } public static String getBigValue(String str, MyFun myFun) { return myFun.getValue(str); } public static void longT(Long l1,Long l2, MyFunction2<Long,Long> myFunction2) { Long value = myFunction2.getValue(l1, l2); System.out.println("value = " + value); } }
-
再计算两个long型参数的乘积
/** * 两个long型参数的乘积 */ longT(100L,200L,(e1,e2)->e1*e2);
Java内置四大核心接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer 消费性接口 | T | void | 对类型为T的对象应用操作,包含方法:void accept(T t) |
Supplier 供给型接口 | 无 | T | 返回类型为T的对象,包含方法 T get() |
Function<T,R> 函数新接口 | T | R | 对类型为T的对象应用操作,并返回结果。结果是R的类型对象,包含方法: R apply(T t); |
Predicate 断定型接口 | T | boolean | 确定T类型的对象是否满足某种约束,并返回boolean值。包含方法 boolean test(T t); |
-
消费型接口
package org.lfh.java8.lambdafourkey; import java.util.function.Consumer; /** * @author lifh * @creat 2020/10/25/22:54 */ public class FourKey { public static void main(String[] args) { /** * Consumer消费性接口 */ consumerTest(1000,x-> System.out.println("每次❀"+x+"买吃的")); } public static void consumerTest(Integer money, Consumer<Integer> consumer){ consumer.accept(money); } }
-
供给型接口
package org.lfh.java8.lambdafourkey; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; /** * @author lifh * @creat 2020/10/25/22:54 */ public class FourKey { public static void main(String[] args) { /** * Supplier供给型接口 * 产生指定个数整数,并放入集合 */ List<Integer> integers = supplierTest(10, () -> (int) (Math.random() * 100)); System.out.println("integers = " + integers); } public static List<Integer> supplierTest(int num,Supplier<Integer> supplier){ ArrayList<Integer> arrayLis=new ArrayList<>(); for (int i=0;i<=num;i++){ Integer number = supplier.get(); arrayLis.add(number); } return arrayLis; } }
-
函数型接口
package org.lfh.java8.lambdafourkey; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; /** * @author lifh * @creat 2020/10/25/22:54 */ public class FourKey { public static void main(String[] args) { /** * 函数式接口 * 处理字符串 */ String str = functionTest("lfh", x -> x.toUpperCase()); System.out.println("lfh = " + str); } public static String functionTest(String str, Function<String,String> function){ String apply = function.apply(str); return apply; } }
-
断定行接口
package org.lfh.java8.lambdafourkey; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; /** * @author lifh * @creat 2020/10/25/22:54 */ public class FourKey { public static void main(String[] args) { /** * 断定型接口 * 判断一个int类型的数是否大于1024 */ Boolean aBoolean = predicateTest(100, x -> x > 1024); System.out.println("aBoolean = " + aBoolean); } public static Boolean predicateTest(int number, Predicate<Integer> predicate){ boolean test = predicate.test(number); return test; } }