java 8引入了lambda表達式,lambda表達式實際上表示的就是一個匿名的function。java
在java 8以前,若是須要使用到匿名function須要new一個類的實現,可是有了lambda表達式以後,一切都變的很是簡介。git
咱們看一個以前講線程池的時候的一個例子:github
//ExecutorService using class
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(new Runnable() {
@Override
public void run() {
log.info("new runnable");
}
});
複製代碼
executorService.submit須要接收一個Runnable類,上面的例子中咱們new了一個Runnable類,並實現了它的run()方法。app
上面的例子若是用lambda表達式來重寫,則以下所示:ide
//ExecutorService using lambda
executorService.submit(()->log.info("new runnable"));
複製代碼
看起是否是很簡單,使用lambda表達式就能夠省略匿名類的構造,而且可讀性更強。this
那麼是否是全部的匿名類均可以用lambda表達式來重構呢?也不是。lua
咱們看下Runnable類有什麼特色:spa
@FunctionalInterface
public interface Runnable 複製代碼
Runnable類上面有一個@FunctionalInterface註解。這個註解就是咱們今天要講到的Functional Interface。線程
Functional Interface是指帶有 @FunctionalInterface 註解的interface。它的特色是其中只有一個子類必需要實現的abstract方法。若是abstract方法前面帶有default關鍵字,則不作計算。code
其實這個也很好理解,由於Functional Interface改寫成爲lambda表達式以後,並無指定實現的哪一個方法,若是有多個方法須要實現的話,就會有問題。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
複製代碼
Functional Interface通常都在java.util.function包中。
根據要實現的方法參數和返回值的不一樣,Functional Interface能夠分爲不少種,下面咱們分別來介紹。
Function接口定義了一個方法,接收一個參數,返回一個參數。
@FunctionalInterface
public interface Function<T, R> {
/** * Applies this function to the given argument. * * @param t the function argument * @return the function result */
R apply(T t); 複製代碼
通常咱們在對集合類進行處理的時候,會用到Function。
Map<String, Integer> nameMap = new HashMap<>();
Integer value = nameMap.computeIfAbsent("name", s -> s.length());
複製代碼
上面的例子中咱們調用了map的computeIfAbsent方法,傳入一個Function。
上面的例子還能夠改寫成更短的:
Integer value1 = nameMap.computeIfAbsent("name", String::length);
複製代碼
Function沒有指明參數和返回值的類型,若是須要傳入特定的參數,則可使用IntFunction, LongFunction, DoubleFunction:
@FunctionalInterface
public interface IntFunction<R> {
/** * Applies this function to the given argument. * * @param value the function argument * @return the function result */
R apply(int value);
}
複製代碼
若是須要返回特定的參數,則可使用ToIntFunction, ToLongFunction, ToDoubleFunction:
@FunctionalInterface
public interface ToDoubleFunction<T> {
/** * Applies this function to the given argument. * * @param value the function argument * @return the function result */
double applyAsDouble(T value);
}
複製代碼
若是要同時指定參數和返回值,則可使用DoubleToIntFunction, DoubleToLongFunction, IntToDoubleFunction, IntToLongFunction, LongToIntFunction, LongToDoubleFunction:
@FunctionalInterface
public interface LongToIntFunction {
/** * Applies this function to the given argument. * * @param value the function argument * @return the function result */
int applyAsInt(long value);
}
複製代碼
若是須要接受兩個參數,一個返回值的話,可使用BiFunction:BiFunction, ToDoubleBiFunction, ToIntBiFunction, ToLongBiFunction等。
@FunctionalInterface
public interface BiFunction<T, U, R> {
/** * Applies this function to the given arguments. * * @param t the first function argument * @param u the second function argument * @return the function result */
R apply(T t, U u);
複製代碼
咱們看一個BiFunction的例子:
//BiFunction
Map<String, Integer> salaries = new HashMap<>();
salaries.put("alice", 100);
salaries.put("jack", 200);
salaries.put("mark", 300);
salaries.replaceAll((name, oldValue) ->
name.equals("alice") ? oldValue : oldValue + 200);
複製代碼
若是什麼參數都不須要,則可使用Supplier:
@FunctionalInterface
public interface Supplier<T> {
/** * Gets a result. * * @return a result */
T get();
}
複製代碼
Consumer接收一個參數,可是不返回任何值,咱們看下Consumer的定義:
@FunctionalInterface
public interface Consumer<T> {
/** * Performs this operation on the given argument. * * @param t the input argument */
void accept(T t);
複製代碼
看一個Consumer的具體應用:
//Consumer
nameMap.forEach((name, age) -> System.out.println(name + " is " + age + " years old"));
複製代碼
Predicate接收一個參數,返回boolean值:
@FunctionalInterface
public interface Predicate<T> {
/** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} */
boolean test(T t);
複製代碼
若是用在集合類的過濾上面那是極好的:
//Predicate
List<String> names = Arrays.asList("A", "B", "C", "D", "E");
List<String> namesWithA = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());
複製代碼
Operator接收和返回一樣的類型,有不少種Operator:UnaryOperator BinaryOperator ,DoubleUnaryOperator, IntUnaryOperator, LongUnaryOperator, DoubleBinaryOperator, IntBinaryOperator, LongBinaryOperator等。
@FunctionalInterface
public interface IntUnaryOperator {
/** * Applies this operator to the given operand. * * @param operand the operand * @return the operator result */
int applyAsInt(int operand);
複製代碼
咱們看一個BinaryOperator的例子:
//Operator
List<Integer> values = Arrays.asList(1, 2, 3, 4, 5);
int sum = values.stream()
.reduce(0, (i1, i2) -> i1 + i2);
複製代碼
Functional Interface是一個很是有用的新特性,但願你們可以掌握。
本文的例子:github.com/ddean2009/l…
更多內容請訪問 www.flydean.com