一、Functional接口
- 函数式接口,有且仅有一个抽象方法,Object的public方法除外。
- 函数式接口的一大特性就是可以被lambda表达式和函数引用表达式代替。也就是说声明这样的接口,是可以灵活的以方法来传参。
- 以下是Java8内置四大核心函数式接口:
1) 消费型接口
//Represents an operation that accepts a single input argument and returns no result.
@FunctionalInterface
public interface Consumer<T> { void accept(T t); }
Consumer简单例子:
public class MethodReferenceTest {
@Test
public void testConsumer(){
age(18, a -> System.out.println("my age is: " + a));
}
public void age(int x, Consumer consumer){
consumer.accept(x);
}
}
2) 供给型接口
//There is no requirement that a new or distinct result be returned each time the supplier is invoked.
@FunctionalInterface
public interface Supplier<T> { T get(); }
Supplier简单例子:
public class MethodReferenceTest {
@Test
public void testSupplier(){
List<Double> list = supplierMethod(10, ()-> Math.random());
for (Double i: list){
System.out.println(i);
}
}
//产生指定个数的整数并放入集合中
public List<Double> supplierMethod(int num, Supplier<Double> supplier){
List<Double> list = new ArrayList<>();
for (int i=0; i<num; i++){
list.add(supplier.get());
}
return list;
}
}
3) 函数型接口
//Represents a function that accepts one argument and produces a result.
@FunctionalInterface
public interface Function<T, R> { R apply(T t); }
Function简单例子:
public class MethodReferenceTest {
//函数型接口测试
@Test
public void testFunction(){
String resStr = strHandler("\t \t Hello Function ", str->str.trim());
System.out.println(resStr);
}
public String strHandler(String s, Function<String, String> function){
return function.apply(s);
}
}
4) 断言型型接口
//Represents a predicate (boolean-valued function) of one argument.
@FunctionalInterface
public interface Predicate<T> { boolean test(T t); }
Predicate简单例子:
public class MethodReferenceTest {
//断言型接口测试
@Test
public void testPercidate(){
List<Integer> numList = Arrays.asList(12,130,123,32,45,612,95,100,139);
List<Integer> l = filterNum(numList,num->num>100);
for(Integer i : l){
System.out.println(i);
}
}
public List<Integer> filterNum(List<Integer> numList, Predicate<Integer> predicate){
List<Integer> resList = new ArrayList<>();
for (Integer num : numList){
if(predicate.test(num)){
resList.add(num);
}
}
return resList;
}
}
二、方法引用
- 若Lambda体的内容有方法已经实现了,就可以使用方法引用。可以理解为方法引用是Lambda表达式的另外一种表现形式。
- Lambda体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致。
例如:public void println(Object x) {} 与void accept(T t); 返回值和参数一致
主要有三种语法格式:
对象::实例方法名
public class MethodReferenceTest {
//对象::实例方法名(非静态方法)
//public void println(Object x) {} 和void accept(T t); 返回值和参数一致
@Test
public void object_method_reference_Test() {
PrintStream printStream = System.out; //PrintStream 对象
Consumer cs1 = x -> printStream.println(x); //lambda表达式写法
cs1.accept("test cs1");
Consumer cs2 = printStream::println; //当lambda表达式时对象调用实例方法时可用方法引用(对象::实例方法名)
cs2.accept("test cs2");
Consumer cs3 = System.out::println; //合并写法
cs3.accept("test cs3");
}
}
类::静态方法名
public class MethodReferenceTest {
@Test
public void class_referenct_static_method() {
//Integer中的compare方法为static的 public static int compare(int x, int y) {
Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
/**Compares its two arguments for order. Returns a negative integer,zero,
or a positive integer as the first argument is less than, equal to, or greater than the second.
**/
int res = comparator.compare(3, 3);
System.out.println(res);
Comparator<Integer> comparator1 = Integer::compare;
int res1 = comparator1.compare(10, 3);
System.out.println(res1);
}
}
类::实例方法名
使用条件:Lambda参数列表中的第一个参数是实例方法的调用者,第二个参数是实例方法的参数时
public class MethodReferenceTest {
@Test
public void class_reference_method(){
BiPredicate<String, String> biPredicate = (x,y)->x.equals(y);
System.out.println(biPredicate.test("abc", "abc"));
BiPredicate<String, String> biPredicate1 = String::equals;
System.out.println(biPredicate1.test("ert", "ert"));
}
}
三、构造器引用
- 格式:ClassName::new
- 需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致!
public class ConstructorReferenceTest {
@Test
public void constructor_referent_test(){
Function<String,Account> supplier = (x)->new Account(x);
Account account = supplier.apply("vivi");
System.out.println(account);
Function<String,Account> supplier1 = Account::new;
Account account1 = supplier1.apply("Vivi");
System.out.println(account1);
}
}
public class Account {
private String name;
private double money;
public Account(String name) {
this.name = name;
}
...set/get...
}
四、数组引用
- 格式:Type[]::new
public class ArrayReferenceTest {
@Test
public void array_referenct_test(){
Function<Integer,String[]> function = x->new String[x];
String[] strings = function.apply(10);
System.out.println(strings.length);
Function<Integer, String[]> function1 = String[]::new;
String[] strings1 = function1.apply(12);
System.out.println(strings1.length);
}
}