Lamada表达式
示例代码
首先提供只有一个抽象方法的接口(函数式接口),这个可以自己定义,或者JDK8中国声明在java.util.function包下的函数式接口
@FunctionalInterface
public interface MyFunctionalInterface {
void method();
}
Lamada表达式案例
public class MyFunctionalInterfaceTest {
@Test
public void test(){
MyFunctionalInterface mfi = ()->{
System.out.println("未必要活在振奋里");
};
mfi.method();
}
}
语法规则
->左边:Lamada形参列表,无参数时提供一对(),参数类型可以省略(类型推断),只有一个参数时可以省略括号
->右边:Lamda体,对应重写方法的方法体。如果只有一条执行语句,则{}可以省略,如果有return关键字,必须一并省略。参考如下代码
//语法格式六:当 Lambda 体只有一条语句时,return 与大括号若有,都可以省略
@Test
public void test6() {
Comparator<Integer> com1 = (o1, o2) -> {
return o1.compareTo(o2);
};
System.out.println(com1.compare(12, 6));
System.out.println("*****************************");
Comparator<Integer> com2 = (o1,o2)->o1.compareTo(o2);
}
理解
Lamada表达式既是接口的实现类对象(体现类万事万物皆对象),又是一个匿名函数。
方法引用与构造器引用
方法引用主要是对lamada表达式的进一步简化,具体使用情况如下:
Case1 :对象::实例方法
@Test
public void test1() {
Consumer<String> con1 = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con1.accept("hello");
Consumer<String> consumer=s->System.out.println(s);
Consumer<String> consumer1 = System.out::println;
}
其中Consumer接口如下,要记住参数和抽象方法,只接受不返回。
public interface Consumer<T> {
void accept(T t);
}
可以看到抽象方法中accpet和内部调用System.out对象的println方法的形参类别和返回值类型都相同,此时直接用println方法覆盖原有的。采用对象调方法的方式,参数类型可由接口的<String>推断。
总结:
要求:函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b的形参列表和返回值类型都相同(或一致)。 此时,可以考虑使用方法b实现对方法a的替换、覆盖。此替换或覆盖即为方法引用。 注意:此方法b是非静态的方法,需要对象调用。
case 2:类::静态方法
//Comparator中的int compare(T t1,T t2)
//Integer中的int compare(T t1,T t2)
@Test
public void test3() {
Comparator<Integer> con1 = (o1,o2)->Integer.compare(o1,o2);
System.out.println(con1.compare(23, 12));
Comparator<Integer> con2 = Integer::compare;
//下面这句属于第三种情况:类::实例方法,放在这里注意区分。
Comparator<Integer> con3= Integer::compareTo;
}
Integer类的compare方法结构如下:
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
Comparator接口结构如下
public interface Comparator<T> {
int compare(T o1, T o2);
}
与Case1类似,参数列表和返回值相同,只不过这个方法是静态的,可以直接通过类调用而已。
case 3:类::实例方法
//BiPredicate中的boolean test(T t1, T t2);
//String中的boolean t1.equals(t2)
@Test
public void test6() {
BiPredicate<String,String> biPredicate = (s1,s2)->s1.equals(s2);
BiPredicate<String,String> biPredicate1 = String::equals;
BiPredicate<String,String>biPredicate2 = String::equals;
}
BiPredicate结构如下:
public interface BiPredicate<T, U> {
/**
* Evaluates this predicate on the given arguments.
*
* @param t the first input argument
* @param u the second input argument
* @return {@code true} if the input arguments match the predicate,
* otherwise {@code false}
*/
boolean test(T t, U u);
String类型的equals方法结构:public boolean equals(Object anObject)
以此代码为例:抽象方法test与equals的返回值类型相同,都是boolean。
同时test有两个参数(n个参数),equals有1个参数(n-1个参数),且抽象方法test的第一个参数作为equals方法的调用者,且抽象方法test后n-1个参数与equals的n-1个参数类型相同或一致(一致主要考虑自动装箱拆箱一类,比如Integer和int型),在此代码中后n-1个为空参。
注意:此方法b是非静态的方法,需要对象调用。但是形式上,写成对象所属的类。
构造器引用
调用哪个构造器主要取决于函数时接口的抽象方法的形参列表。
调用空参构造器:主要用的是supplier
//1.
Supplier<Employee> sup1 = new Supplier<Employee>() {
@Override
public Employee get() {
return new Employee();
}
};
System.out.println(sup1.get());
//2.构造器引用
Supplier<Employee> sup2 = Employee::new; //调用的是Employee类中空参的构造器
System.out.println(sup2.get());
}
//Supplier接口形式,只返回不接受
@FunctionalInterface
public interface Supplier<T> {
T get();
}
调用一个参数构造器:主要用的是Function
//Function中的R apply(T t)
@Test
public void test2(){
//1.
Function<Integer,Employee> func1 = new Function<Integer, Employee>() {
@Override
public Employee apply(Integer id) {
return new Employee(id);
}
};
System.out.println(func1.apply(12));
//2.构造器引用
Function<Integer,Employee> func2 = Employee :: new; //调用的是Employee类中参数是Integer/int类型的构造器
System.out.println(func2.apply(11));
}
//Function接口结构:不要忘记指定返回值类型
public interface Function<T, R> {
R apply(T t);
}
调用一个参数构造器:主要用的是BiFunction,两个参数确定一个结果
//BiFunction中的R apply(T t,U u)
@Test
public void test3(){
//1.
BiFunction<Integer,String,Employee> func1 = new BiFunction<Integer, String, Employee>() {
@Override
public Employee apply(Integer id, String name) {
return new Employee(id,name);
}
};
System.out.println(func1.apply(10, "Tom"));
//2.
BiFunction<Integer,String,Employee> func2 = Employee::new;//调用的是Employee类中参数是Integer/int、String类型的构造器
System.out.println(func2.apply(11, "Tony"));
}
//BiFunction接口结构
public interface BiFunction<T, U, R> {
R apply(T t, U u);
}
Stream API使用
stream的创建
List<Employee> list = EmployeeData.getEmployees();
//通过集合
Stream<Employee> stream = list.stream();
//通过数组
Integer[] arr = new Integer[]{1,2,3,4,5};
Stream<Integer> stream = Arrays.stream(arr);