JDK8.0(1.8)的新特性:
Lambda表达式:
就是一个匿名函数(方法),可以把lambda表达式理解为是一段可以传递的代码.(向数据一样传递)
利用lambda表达式可以写出更简洁,灵活的代码.作为一种更紧凑的代码风格.使java的表达能力得到提升
Lambda 表达式:
在java中引入了一个新的语法元素和操作符 “->”,该操作符称为lambda操作符或者箭头符号.它将lambda表达式
分为两部分:
左侧部分: 指定了lambda表达式需要的所有参数
右侧部分: 指定了lambda体,即lambda表达式要执行的功能
Lambda 表达式语法:
语法1 : 无参数 无返回值
Runnable r2 = () -> System.out.println("limbda表达式");
语法2: 有参数 没有返回值
Consumer<String> con2 = (str) -> System.out.println(str);
语法3: 若只有一个参数,并且没有返回值"()"也可以省略
Consumer<String> con3 = x -> System.out.println(x);
语法4: 有两个以上的参数, 还有返回值, lambda体中有多条语句,Lambda则必须写"{}"
Comparator<Integer> con1 = (x, y) ->
{
System.out.println("这是临时比较规则的接口");
return Integer.compare(x, y);
};
语法5: 若Lambda体中只有一条语句, 则return和"{}"都可以省略
Comparator<Integer> con1 = (x, y) -> Integer.compare(x, y);
语法6: lambda 表达式的参数列表的数据类型可以省略不写. JVM可以通过上下文推断出数据类型,即"类型推断";
Comparator<Integer> con1 = (x, y) -> // (Integer x,Integer y)->{}; //括号中的数据类型可以省略不写
{
System.out.println("语法格式6");
return Integer.compare(x, y);
};
Lambda表达式需要函数式接口的支持
为了将 Lambda 表达式作为参数传递,接收Lambda 表达式的参数类型必须是与该 Lambda 表达式兼容的函数式接口的类型。
函数式接口:
接口中只有一个抽象方法的接口,称为函数式接口
可以使用注解 @FunctionalInterface 修饰,可以检查该接口是否为函数式接口
示例:
@FunctionalInterface //函数式接口修饰注解
public interface MyPredicate<T>
{
public boolean test(T t);
}
Java8内置的四大核心函数式接口
1.Consumer : 消费性接口
void accept(T t); 对类型为T的对象进行操作
2.Supplier : 供给型接口
T get(); 返回类型为T的对象
3.Function<T,R>: 函数型接口
R apply(T t); 对类型为T的对象进行操作,并返回R类型的结果
4.Predicate : 断言型接口
boolean test(T t); 确定T类型的对象是否满足某个约束条件(自定义)
代码示例:
package jdk8;
import java.util.ArrayList;
import java.util.Arrays;
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 lym
*@Description: Java8内置的四大核心函数式接口
*
*@date 2019年12月5日 下午4:54:53
*/
public class FunctionalInterfaceDemo
{
public static void main(String[] args)
{
// 测试消费型接口
happy(998, (m) -> System.out.println("出去 happy 消费了:" + m + "元"));
// 测试供给型接口
List<Integer> list = getNumList(5, () -> (int) (Math.random() * 100));
System.out.println(list);
// 测试函数型接口
String newStr = strHandler(" i like java ", (str) -> str.trim());
System.out.println(newStr);
// 测试断言型接口
List<String> filterStr = Arrays.asList("hello", "学码思", "lambda", "this is kobe");
List<String> strList = filterStr(filterStr, (s) -> s.length() > 3);
System.out.println(strList);
}
/**
* Consumer<T> : 消费性接口
* @param money
* @param con
*/
public static void happy(double money, Consumer<Double> con)
{
con.accept(money);
}
/**
* Supplier<T> : 供给型接口
* 需求:
* 生产指定格式的整数,并且放置在集合中
* @param num
* @param sup
* @return
*/
public static List<Integer> getNumList(int num, Supplier<Integer> sup)
{
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < num; i++)
{
Integer n = sup.get();
list.add(n);
}
return list;
}
/**
* Function<T,R>: 函数型接口
* 需求:
* 用于处理字符串,传进去一个字符串,处理后返回一个字符串
* @param str
* @param fun
* @return
*/
public static String strHandler(String str, Function<String, String> fun)
{
return fun.apply(str);
}
/**
* Predicate<T> : 断言型接口 需求: 将满足条件的字符串提取出来放置在集合中返回
*
*/
public static List<String> filterStr(List<String> strList, Predicate<String> pre)
{
List<String> strlist = new ArrayList<>();
for (String s : strList)
{
if (pre.test(s))
{
strlist.add(s);
}
}
return strlist;
}
}
其他函数式接口:
方法引用和构造器引用:
方法引用:
若lambda体中内容已经有方法实现了,可以使用方法引用(可以理解为是lambda表达式的另外一种体现形式)(实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!)
使用操作符 “::” 将方法名和对象或类的名字分隔开来。
如下三种主要使用情况:
语法格式:
对象::实例方法名
public static void main(String[] args)
{
PrintStream ps = System.out;
/*
* 对象(实例方法所在类的对象)::实例方法名(方法名)
* 前提:
* println()要和accept();方法的参数列表返回值一致
*/
Consumer<String> con = (x) -> ps.println(x);
con.accept("i like java");
Consumer<String> con1 = ps::println;
con1.accept("哈哈哈");
// 练习
Employee employee = new Employee();
// lambda表达式
Supplier<String> sup = () -> employee.getName();
// 方法引用
Supplier<String> sup1 = employee::getName;
System.out.println(sup.get());
System.out.println(sup1.get());
}
类::静态方法名
// 类::静态方法名
Comparator<Integer> com1 = (x, y) -> Integer.compare(x, y);
Comparator<Integer> com2 = Integer::compare;
类::实例方法名
/*
* 类::实例方法名
* 限制条件:
* x必须是equals()方法的调用者
* y必须作为参数传入这个方法中
*
*/
BiPredicate<String, String> bp1 = (x, y) -> x.equals(y);
bp1.test("kobe", "james");
//方法引用
BiPredicate<String, String> bp2 = String::equals;
当方法有参数时:
等同于:
构造器引用:
格式: ClassName (类名) :: new
/*
* 构造器引用
* 注意:
* 需要调用的构造器参数列表要与函数是接口中的抽象方法的参数列表一致
*/
Supplier<Employee> sup1 = () -> new Employee();
Supplier<Employee> sup2 = Employee::new; //构造器引用
Function<Integer, Employee> fun1 = Employee::new; //构造器引用
Employee emp1 = fun1.apply(25);
数组引用:
格式: type[] :: new
等同于:
接口中的默认方法和静态方法
public interface Myfun
{
// 默认方法
default String getName()
{
return "";
}
// 静态方法
public static void show()
{
System.out.println("接口中的静态方法");
}
}