有且只包含一个抽象方法的接口,称为函数式接口。
可以通过Lambda表达式来创建函数式接口的对象(只有函数式接口才能用Lambda表达式)。
可以使用@FunctionalInterface来声明是一个函数式接口。
常见的函数式接口:java.lang.Runnable、java.util.Comparator。
package com.morris.java8.lamdba;
public class RunnableExample {
public static void main(String[] args) {
// 匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " is running.");
}
}).start();
// lamdba
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " is running.");
}).start();
// 进一步简化
new Thread(() -> System.out.println(Thread.currentThread().getName() + " is running.")).start();
}
}
java.util.function包中定义了大量的函数接口,下表列出了这些接口,并对其做一些简单的介绍。
接口名 | 说明 |
---|---|
BiConsumer | 接受两个不同类型的参数,但不返回任何结果的操作 |
BiFunction<T,U,R> | 接受两个不同类型的参数,并返回一个其它类型的结果的操作 |
BinaryOperator | 接受两个相同类型的参数,并返回一个同一类型的结果的操作 |
BiPredicate<T,U> | 接受两个不同诶行的参数,且返回布尔类型的结果的操作 |
BooleanSupplier | 不接受任何参数,且返回一个布尔类型的结果的操作 |
Consumer | 接受一个参数,但不返回任何结果的操作 |
DoubleBinaryOperator | 接受两个double类型的参数,并返回double类型结果的操作 |
DoubleConsumer | 接受一个 double 类型的参数,但不返回任何结果的操作 |
DoubleFunction | 接受一个double类型的参数,且返回一个 R 类型的结果的操作 |
DoublePredicate | 接受两个double类型的参数, 且返回一个布尔类型的结果的操作 |
DoubleSupplier | 不接受任何参数,但返回布尔类型的结果的操作 |
DoubleToIntFunction | 接受两个double类型的参数,但返回一个int类型的结果的操作 |
DoubleToLongFunction | 接受两个double类型的参数,但返回一个long类型的结果的操作 |
DoubleUnaryOperator | 接受一个double类型的参数,且返回一个double类型的结果的操作 |
Function<T,R> | 接受T类型的参数,且返回一个R类型结果的函数 |
IntBinaryOperator | 接受两个int类型的参数,且返回一个int类型的结果的操作 |
IntConsumer | 接受一个int类型的参数,但不返回任何结果的操作 |
IntFunction | 接受一个int类型的参数,但返回一个 R 类型的结果的操作 |
IntPredicate | 接受一个int类型的参数,但返回布尔类型的结果的操作 |
IntSupplier | 不接受任何参数,但返回一个int类型的结果的操作 |
IntToDoubleFunction | 接受一个int类型的参数,但返回一个double类型的结果的操作 |
IntToLongFunction | 接受一个int类型的参数,但返回一long类型的结果的操作 |
IntUnaryOperator | 接受一个int类型的参数,且返回一个int类型的结果的操作 |
LongBinaryOperator | 接受两个long类型的参数,且返回一个long类型的结果的操作 |
LongConsumer | 不接受任何参数,但返回一个long类型的结果的操作 |
LongFunction | 接受一个long类型的参数,但返回一个R类型的结果的操作 |
LongPredicate | 接受一个long类型的参数,但返回布尔类型的结果的操作 |
LongSupplier | 不接受任何参数,但返回一个lon 类型的结果的操作 |
LongToDoubleFunction | 接受一个long类型的参数,但返回一个double类型的结果的函数 |
LongToIntFunction | 接受一个long类型的参数,但返回int类型的结果的函数 |
LongUnaryOperator | 接受一个long类型的参数,并返回一个long类型的结果的操作 |
ObjDoubleConsumer | 接受两个参数,一个为T类型的对象,另一个double类型,但不返回任何结果的操作 |
ObjIntConsumer | 接受两个参数,一个为T类型的对象,另一个int类型,但不返回任何结果的操作 |
ObjLongConsumer | 接受两个参数,一个为T类型的对象,另一个double类型,但不返回任何结果的操作 |
Predicate | 接受一个指定类型T的参数,但返回布尔类型的结果的操作 |
Supplier | 不接受任何参数,但返回一个T类型的结果的操作 |
ToDoubleBiFunction<T,U> | 接受两个不同类型的参数,但返回一个double类型的结果的操作 |
ToDoubleFunction | 一个接受指定类型T的参数,并返回一个double类型的结果的操作 |
ToIntBiFunction<T,U> | 接受两个不同类型的参数,但返回一个int类型的结果的操作 |
ToIntFunction | 接受指定类型T的参数,并返回一个int类型的结果的操作 |
ToLongBiFunction<T,U> | 接受两个不同类型的参数,但返回一个long类型的结果的操作 |
ToLongFunction | 接受指定类型的参数,并返回一个long类型的结果的操作 |
UnaryOperator | 接受一个参数,并返回一个与参数类型相同的结果的操作 |
package com.morris.java8.lamdba;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class PredicatExample {
public static void main(String[] args) {
List<Integer> integerList = Arrays.asList(1, 3, 5, 4, 8, 9);
List<Integer> result = filterEvenNumber(integerList, i -> i % 2 == 0);
System.out.println(result);
}
public static List<Integer> filterEvenNumber(List<Integer> integerList, Predicate<Integer> predicate) {
List<Integer> result = new ArrayList<>();
for (Integer integer : integerList) {
if(predicate.test(integer)) {
result.add(integer);
}
}
return result;
}
}
package com.morris.java8.lamdba;
import java.util.Arrays;
import java.util.List;
public class ComsumerExample {
public static void main(String[] args) {
List<Integer> integerList = Arrays.asList(1, 3, 5, 4, 8, 9);
integerList.forEach(System.out::println);
}
}
package com.morris.java8.lamdba;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class FunctionExample {
public static void main(String[] args) {
List<String> stringList = Arrays.asList("java", "hello", "world", "function");
List<Integer> result = getLength(stringList, String::length);
System.out.println(result);
}
public static List<Integer> getLength(List<String> stringList, Function<String, Integer> function) {
List<Integer> integerList = new ArrayList<>();
for (String s : stringList) {
integerList.add(function.apply(s));
}
return integerList;
}
}
package com.morris.java8.lamdba;
import com.morris.java8.collector.Dish;
import java.nio.file.DirectoryStream;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class PredicateComplexExample {
public static void main(String[] args) {
List<Dish> dishList = Dish.createList();
// 与-and
// 找出卡路里>300的蔬菜
Predicate<Dish> vegetablePredicate = Dish::isVegetarian;
Predicate<Dish> moreThan300Predicate = d -> d.getCalories() >= 300;
List<Dish> filter = filter(dishList, vegetablePredicate.and(moreThan300Predicate));
System.out.println(filter);
// 非-negate
// 找出荤菜
List<Dish> filter1 = filter(dishList, vegetablePredicate.negate());
System.out.println(filter1);
// 或-or
// 找出卡路里大于300或者荤菜
List<Dish> filter2 = filter(dishList, vegetablePredicate.or(moreThan300Predicate));
System.out.println(filter2);
}
public static List<Dish> filter(List<Dish> dishList, Predicate<Dish> predicate) {
List<Dish> result = new ArrayList<>();
for (Dish dish : dishList) {
if(predicate.test(dish)) {
result.add(dish);
}
}
return result;
}
}
package com.morris.java8.lamdba;
import java.util.function.Function;
public class FunctionComplexExample {
public static void main(String[] args) {
// andThen
Function<Integer, Integer> f = x -> x + 1; // f(x)
Function<Integer, Integer> g = x -> x * 2; // g(x)
Function<Integer, Integer> andThen = f.andThen(g); // g(f)=g(f(x))
Integer apply = andThen.apply(1);
System.out.println(apply);
// compose
Function<Integer, Integer> y = x -> x + 1; // y(x)
Function<Integer, Integer> z = x -> x * 2; // z(x)
Function<Integer, Integer> compose = y.compose(z); // y(z)=y(z(x))
Integer apply2 = compose.apply(1);
System.out.println(apply2);
}
}