前言
隨着函數式編程的流程,Java8中也引入了函數式編程風格(Lambda表達式)。Lambda表達式允許我們將行爲傳遞到函數中,其可以替換匿名內部類實現的繁瑣的代碼。下面就是一個最經典的例子,用普通的匿名內部類一共用了6行代碼,使用Lambda表達式只需要1行代碼即可。也就是說,Lambda表達式在經常使用內部類情況下,可以大大的減少代碼量,還有就是Lambda表達式經常和Stream API一起使用。
// 匿名內部類
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("do something");
}
};
// Lambda表達式
Runnable runnable2 = () -> System.out.println("do something");
Lambda表達式使用
Lambda表達式格式
(Type1 param1, Type2 param2, ..., TypeN typeN) -> {
statment1;
statment2;
// ......
return statmentM;
}
操作符'->':Lambda操作符,該箭頭將Lambda表達式拆分爲左右兩部分
左側:參數列表,只有一個參數時可以不寫()
右側:Lambda表達式體,就抽象方法實現區域。只有一行代碼時可以不寫{},參數類型也可以不用寫(Java會通過上下文進行判斷)
上面是標準的Lambda表達式,一般情況下Lambda表達式可以分爲以下幾種類型:
無參數無返回值
() -> {
statment1;
statment2;
...
statmentN;
}
有參數無返回值
(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
statment1;
statment2;
...
statmentN;
}
有參數有返回值
(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
statment1;
statment2;
...
statmentN;
return value;
}
下面是一個實現List排序功能(根據字符串長度)的例子,可以看到這個例子是有參有返回值的,但是沒有寫return值(在單見場景下可以省略不寫)
List<String> list = new ArrayList<>();
list.add("my");
list.add("name");
list.add("is");
list.add("super");
list.add("man");
// 非lambda實現排序
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
list.stream().forEach((x)->System.out.println(x));
// lambda實現排序
Collections.sort(list, (o1, o2) -> o2.length() - o1.length());
list.stream().forEach((x)->System.out.println(x));
函數式接口
定義與Lambda關係
函數式接口就是一個有且僅有一個抽象方法,但是有多個非抽象方法的接口。Lambda表達式需要函數式接口的支持,下面是自定義的函數式接口:
@FunctionalInterface
public interface TestService {
void test();
}
// 使用代碼
TestService testService = ()->System.out.println("test");
testService.test();
@FunctionalInterface註解用於標識該接口是函數式接口,如果不滿足函數式接口規則,則編譯會報錯,當然函數式接口並不一定需要@FunctionalInterface註解。
Java中四種函數式接口
Java中常用的四個核心函數式接口包括:1、Consumer<T> 消費型接口;2、Supplier<T> 供給型接口;3、Function<R, T> 函數型接口;4、Predicate<T> 斷言型接口
消費型接口(Consumer<T>)
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
主要方法:
accept(T t):接受一個指定類型的參數,但無返回值
andThen(Consumer<? super T> after):從左向右執行
List<String> list2 = Arrays.asList("a","bb","ccc","dddd","eeeee");
Consumer<String> consumer = (x) -> System.out.println("input:" + x);
list2.stream().forEach(consumer);
供給型接口(Supplier<T>)
@FunctionalInterface
public interface Supplier<T> {
T get();
}
主要方法:
T get():不接受任何參數,但返回執行類型的值
List<Integer> list1 = new ArrayList<>();
Supplier<Integer> supplier = () -> (int)(Math.random() * 100);
for (Integer i = 0; i < 10; i++) {
list1.add(supplier.get());
}
list1.stream().forEach((x) -> System.out.println(x));
函數型接口(Function<R, T>)
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
主要方法:
R apply(T t):接受一個指定類型的參數,返回一個執行的結果類型
andThen和compose方法:執行順序不一樣,andThen是從左向右執行;compose是從右向左執行;
Function<String, String> function1 = (x) -> x.toUpperCase();
List<String> list4 = list2.stream().map(function1).collect(Collectors.toList());
for (String elem : list4) {
System.out.println("String Upper:" + elem);
}
Function<Integer, Integer> function2 = (x) -> x * 3;
Function<Integer, Integer> function3 = (x) -> x + 8;
System.out.println("andThen:" + function2.andThen(function3).apply(1));
System.out.println("compose:" + function2.compose(function3).compose(function3).apply(1));
斷言型接口(Predicate<T>)
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
主要方法:
boolean test(T t):傳入指定值用於判斷,返回true或者false
and、negate、or、isEqual方法代表與、非、或、相等。