java语言之jdk1.8的新特性
一、Lambda表达式
(1)概念
Lambda表达式是特殊的匿名内部类,语法更简洁。
Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递。
(2)语法
函数式接口 变量名 = (参数1,参数2…) -> {
//方法体
};
Lambda引入了新的操作符:->(箭头操作符),->将表达式分成两部分:
- 左侧:(参数1,参数2…)表示参数列表
- 右侧:{ }内部是方法体
(3)使用
//匿名内部类
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("线程1执行了!");
}
};
//Lambda表达式
Runnable runnable2 = () -> System.out.println("线程2执行了!");
new Thread(runnable2).start();
new Thread( () -> System.out.println("线程3执行了!")).start();
//匿名内部类
Comparator<String> com = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() + o2.length();
}
};
//Lambda表达式
Comparator<String> com2 = (String o1, String o2) -> {
return o1.length() - o2.length();
};
Comparator<String> com3 = (o1,o2) -> o1.length() - o2.length();
(4)注意
- 接口或者抽象类只允许有一个抽象方法,因此可以使用@FunctionalInterface来约束它。
- 形参列表的数据类型会自动推断。
- 如果形参列表为空,只需保留() 。
- 如果形参只有1个,()可以省略,只需要参数的名称即可。
- 如果执行语句只有一句,且无返回值,{}可以省略,若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有一句。
- Lambda不会生成一个单独的内部类文件。
二、函数式接口
(1)概念
如果一个接口只有一个抽象方法,则该接口称之为函数式接口。
函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上 。
@FunctionalInterface 注解检测接口是否符合函数式接口规范。
(2)常见函数式接口
接口 | 参数类型 | 返回类型 | 说明 |
---|---|---|---|
Consumer< T > 消费型接口 | T | void | void accept(T t); 对类型为T的对象应用操作。 |
Supplier< T > 供给型接口 | 无 | T | T get(); 返回类型为T的对象。 |
Function< T,R > 函数型接口 | T | R | R apply(T t); 对类型为T的对象应用操作,并返回类型为R类型的对象。 |
Predicate< T > 断言型接口 | T | boolean | boolean test(T t); 确定类型为T的对象是否满足条件,并返回boolean类型。 |
(3)案例演示
//Consumer 消费型接口:泛型执行什么类型就可以使用accept方法消费什么类型的数据
public class Demo01 {
public static void main(String[] args) {
happy(t->System.out.println("聚餐消费:"+t), 1000);
happy(t->System.out.println("唱歌消费:"+t), 2000);
}
//Consumer 消费型接口
public static void happy(Consumer<Double> consumer,double money) {
consumer.accept(money);
}
}
//输出结果:
//聚餐消费:1000.0
//唱歌消费:2000.0
//Predicate 断言型接口:对某种数据类型的数据进行判断,结果返回一个boolean值
public class Demo02 {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("zhangsan");
list.add("zhangwuji");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
//输出前面有"zhang"的字符串
List<String> result3=filterNames(s->s.startsWith("zhang"), list);
System.out.println(result3.toString());
//输出长度大于5的字符串
List<String> result4=filterNames(s->s.length()>5, list);
System.out.println(result4);
}
//Predicate 断言型接口
public static List<String> filterNames(Predicate<String> predicate,List<String> list){
List<String> resultList=new ArrayList<String>();
for (String string : list) {
if(predicate.test(string)) {
resultList.add(string);
}
}
return resultList;
}
}
//输出结果:
//[zhangsan, zhangwuji]
//[zhangsan, zhangwuji, wangwu, zhaoliu]
//Supplier 供给型接口:指定接口泛型是什么类型,接口中的get方法就会生产什么类型的数据
public class Demo03 {
public static void main(String[] args) {
//随机生成5位100以内的数
int[] arr=getNums(()->new Random().nextInt(100), 5);
System.out.println(Arrays.toString(arr));
//随机生成10位1000以内的数
int[] arr2=getNums(()->new Random().nextInt(1000), 10);
System.out.println(Arrays.toString(arr2));
}
//Supplier 供给型接口
public static int[] getNums(Supplier<Integer> supplier, int count) {
int[] arr=new int[count];
for(int i=0;i<count;i++) {
arr[i]=supplier.get();
}
return arr;
}
}
//输出结果:
//[5, 58, 20, 26, 15]
//[587, 322, 737, 305, 382, 617, 214, 339, 757, 694]
//Function函数型接口:传入参数T,返回类型R
public class Demo04 {
public static void main(String[] args) {
//将字符串转换成大写
String result1=handlerString(s->s.toUpperCase(), "hello");
System.out.println(result1);
//去除字符串两端多余的空格
String result2=handlerString(s->s.trim(), " zhangsan ");
System.out.println(result2);
}
//Function函数型接口
public static String handlerString(Function<String, String> function, String str) {
return function.apply(str);
}
}
//输出结果:
//HELLO
//zhangsan
三、方法引用
(1)概念
方法引用是Lambda表达式的一种简写形式。
如果Lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用。
(2)常见形式
1)对象::实例方法
Consumer<String> consumer1 = s -> System.out.println(s);
consumer1.accept("hello");
Consumer<String> consumer2 = System.out::println;
consumer2.accept("world");
2)类::静态方法
//2、类::静态方法
Comparator<Integer> com1 = (o1, o2) -> Integer.compare(o1, o2);
Comparator<Integer> com2 = Integer::compare;
3)类::实例方法
//3、类::实例方法
Function<Employee, String> function1 = e -> e.getName();
Function<Employee, String> function2 = Employee::getName;
4)类::new
//4、类::new
Supplier<Employee> supplier1 = () -> new Employee();
Supplier<Employee> supplier2 = Employee::new;