java8新特性大纲
lambda表达式入门
package com.baidu;
import java.util.function.Consumer;
/**
* lambda表达式的使用:
* 1.举例: Comparator<Interger> c = (o1,o2) -> Integer.compare(o1,o2);
* 2.格式
* -> :lambda操作符 或 箭头操作符
* ->左边: lambda参数列表(其实就是抽象方法的参数列表)
* ->右边: lambda体 (其实就是重写抽象方法的方法体)
*
* 3.lambda表达式分为6种情况介绍: 都是针对抽象方法来说的!
* 0/1/多个参数 和 有/无返回值进行一个组合就有六种情况!
* 1.无参,无返回值
* 2.无参,有返回值
* 3.有一个参数,无返回值
* 4.有一个参数,有返回值
* 5.有多个参数,无返回值
* 6.有多个参数,有返回值
*
* 4.在java中lambda表达式的本质:就是作为函数式接口的实例!
*
* 5.可能你感觉这个lambda表达式不就是创建匿名内部类的吗有必要学这么多吗
* 到了后面的Stream流的方法的参数类型,基本上都是函数式接口了!,使用Stream流
* 对集合操作跟操作表差不多!
*
*
* 6.类型推断:
* List<Integer> list = new ArrayList<Integer>();
* 因为有类型推断所以也可以写成如下:
* List<Integer> list = new ArrayList<>();
*
* int[] arr = new int[]{1,2,3};
* 因为有类型推断所以也可以写成如下:
* int[] arr = {1,2,3};
*
* 7.@FunctionalInterface: 它就是可以校验一下你是不是函数式接口!,跟@Override本质一样
*
* 8.函数式接口:接口中只有一个抽象方法:比如Runnable,Comparator不是Comparable
*
* 9.总结
* 注:以前用匿名实现类来表示的,现在都可以用lambda表达式来实现!
* 注:在lambda表达式中,如果方法体中的语句只有一句那么{}可以省了,
* 一旦{}省了,如果该方法有返回值,则return必须省了,
* 但如果方法体中的语句只有一句,如果加了{}, return是根据方法的返回值决定加不加!
* 注:遇见 :: 就是方法引用,遇见 -> 就是lambda表达式!
*/
public class LambdaTest {
public static void main(String[] args) {
noParameterAndNoReturn();
singleParameterAndNoReturn();
}
//单参,无返回值
private static void singleParameterAndNoReturn() {
//第一种写法
Consumer<String> c = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
c.accept("hello world");
//第二种写法:使用lambda表达式之后
Consumer<String> c2 = (String s) -> {
System.out.println(s);
};
c2.accept("虽然帅,但是菜");
//第三种写法:在上面精简一下
/**
* 1.这里省了不写参数的类型,是因为类型推断, 编译器可以推断的出来! 就像泛型和数组中一样
* 2.这里省了不写{}, 是因为当只有一条语句的话,就可以省了{},如果该方法有返回值的话,还可以省了return:前提是只有一条语句!!!
* 3.若只有一个参数,此时参数的小括号也可以省了
*/
Consumer<String> c3 = (s) -> System.out.println(s);
c3.accept("wzj");
Consumer<String> c4 = s -> System.out.println(s);
c3.accept("nb");
}
// 无参,无返回值
private static void noParameterAndNoReturn() {
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("run().....");
}
};
r.run();
// 使用lambda表达式之后
Runnable r2 = () -> {
System.out.println("run2().....");
};
r2.run();
}
}
四大核心函数式接口!
package cn.itcast.lambda;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* java内置的4大核心函数式接口!
* 消费型接口: Consumer<T> void accpet(T t)
* 供给型接口: supplier<T> T get()
* 函数型接口 Function<T,R> R apply(T t)
* 断定型接口: Predicate<T> boolean test(T t)
*/
public class LambdaTest2 {
@Test
public void test1(){
testConsumer(20, new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println("我买了根辣条,消费了"+integer);
}
});
//使用lambda表达式: 因为参数只有一个参数,所以可以省了(), 因为只有一条语句所以可以省了{}
testConsumer(30,integer -> System.out.println("我买了根辣条,消费了"+integer));
}
private static void testConsumer(int money, Consumer<Integer> consumer) {
consumer.accept(money);
}
@Test
public void test2(){
List<String> list = new ArrayList<>(Arrays.asList("春天","夏天","秋天","冬天"));
//一:使用匿名内部类的方式
List<String> filterList = testPredicate(list, new Predicate<String>() {
@Override
public boolean test(String s) {
return s.contains("春");
}
});
System.out.println(filterList);
//二:使用lambda表达式
List<String> filterList2 = testPredicate(list,s -> s.contains("春"));
System.out.println(filterList2);
}
// 根据给定的规则,过滤集合中的字符串, 此规则由Predicate的抽象方法决定!
private static List<String> testPredicate(List<String> list, Predicate<String> filterCondition) {
List<String> filterList = new ArrayList<>();
for (String s:list) {
if (filterCondition.test(s)) {
filterList.add(s);
}
}
return filterList;
}
}
注:
lambda表达式引用了标记了final的外层局部变量
在jdk1.8之前,外部局部变量需要显示的用final修饰
但是jdk8后,虽然不用显示的用final修饰,但它还是具有final修饰的作用!也就是说它还是默认帮你加了final
以下是lambda表达式的重要特征:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但零,多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
就是如果只有一条语句,就无需return, 如果有多条语句就要显示的使用return
来自:虽然帅,但是菜的cxy,每天进步一点点!!