行為參數(shù)化的3中方式(策略模式)
- 類
- 匿名類
- lamada
函數(shù)式接口
函數(shù)式接口就是只定義一個抽象方法的接口。
Lambda表達式允許你直接內(nèi)聯(lián)掘托,為函數(shù)式接口的抽象方法提供實現(xiàn),并且將整個表達式座位函數(shù)式接口的一個實例跑筝。
java.util.function包中引入了的函數(shù)式接口
- Predicate
Interface Predicate<T>
Type Parameters:
T - the type of the input to the predicate
Functional Interface:
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
抽象方法:
boolean test(T t)
Evaluates this predicate on the given argument.
Predicate<T>接口定義了一個名叫test的抽象方法,接收泛型T對象,返回一個boolean站欺。
public class Main {
public static void main(String[] args) {
Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
filter(listOfString, nonEmptyStringPredicate);
}
public static <T> List<T> filter(List<T> list, Predicate<T> p){
List<T> results = new ArrayList<T>();
for(T s : list){
if(p.test(s)){
results.add(s);
}
}
return results;
}
}
- Consumer
Interface Consumer<T>
Type Parameters:
T - the type of the input to the operation
All Known Subinterfaces:
Stream.Builder<T>
Functional Interface:
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
抽象方法
void accept(T t)
Performs this operation on the given argument.
Consumer<T>定義了一個名叫accept的抽象方法蜻懦,它接受泛型T對象甜癞,沒有返回(void)。如果需要訪問類型T的對象阻肩,并對其執(zhí)行某些操作带欢,就可以使用這個接口。
public static <T> void forEach(List<T> list,Consumer<T> consumer){
for(T i:list){
consumer.accept(i);
}
}
forEach(Arrays.asList(1,2,3,4,5),(Integer i) -> System.out.println(i));
- Interface Function<T,R>
Type Parameters:
T - the type of the input to the function
R - the type of the result of the function
All Known Subinterfaces:
UnaryOperator<T>
Functional Interface:
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
抽象方法:
R apply(T t)
Applies this function to the given argument.
Function<T,R>接口定義了一個叫做apply的方法烤惊,它接受一個泛型T的對象乔煞,并返回一個泛型R的對象。如果要定義一個lambda柒室,將輸入對象的信息映射到輸出渡贾,就可以使用這個接口。
public static <T,R> List<R> map(List<T> list, Function<T,R> f){
List<R> result = new ArrayList<>();
for(T s:list){
result.add(f.apply(s));
}
return result;
}
List<Integer> l = map(Arrays.asList("lambdas","in","action"),(String s)->s.length());
}
異常雄右,lambda空骚,還有函數(shù)式接口
任何函數(shù)式接口都不允許拋出受檢異常(checked exception).如果需要Lambda表達式來拋出異常,有兩種辦法:
- 定義字一個自己的函數(shù)式接口擂仍,并聲明受檢異常囤屹。
- 把lambda包在一個try/catch中。
@FunctionalInterface
public interface BufferedReaderProcessor{
String process(BufferdReader b) throws IOException
}
Function<BufferedReader,String> f = (BufferedReader b) ->{
try{
return b.readLine();
}catch(IOException e){
throw new RuntimeException(e);
}
}
Lambda表達式使用局部變量
lambda表達式不僅能用到主體里的函數(shù)逢渔。還允許使用自有變量(不是參數(shù)肋坚,而是在外層作用域中定義的變量),就像匿名類一樣肃廓。他們被稱作捕獲Lambda
int portNumber = 1337;
Runable r = () -> System.out.println(portNumber);
但是,Lambda可以沒有限制的捕獲(也就是在其主題中引用)實例變量和靜態(tài)變量智厌。但是局部變量必須顯示的聲明為final。
閉包
Lambda和匿名類可以做類似于閉包的事情:他們可以作為參數(shù)傳遞給方法盲赊,并且可以訪問其作用域之外的變量铣鹏。但是有一個顯示:他們不能修改定義Lambda的方法的局部變量的內(nèi)容。
方法引用
先前
inventory.sort((Apple a1,Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
之后(使用方法引用后java.util.Comparator.compareing):
inventory.sort(comparing(Apple::getWeight))
如何構(gòu)建方法引用:方法引用主要有3類
- 指向靜態(tài)方法的方法引用(例如Integer的parseInt方法)寫作Integer::parseInt
- 指向任意類型實例方法的方法引用(例如String的length方法,寫作String::length)
-
指向現(xiàn)有對象的實例方法的方法引用(假設(shè)你有一個局部變量expensiveTransaction用于存放Transaaction類型的對象哀蘑,他支持實例方法getValue诚卸,那么你就可以寫expensiveTransaction::getValue)。
image
構(gòu)造函數(shù)引用
對于一個現(xiàn)有的構(gòu)造函數(shù)递礼,可以利用它的名稱和關(guān)鍵字new來創(chuàng)建它的一個引用:ClassName::new惨险。它的功能與指向靜態(tài)方法的引用類似。列入脊髓,假設(shè)有一個構(gòu)造函數(shù)沒有參數(shù)。它適合Supplier的簽名()->Apple栅受。
Suppier<Apple> c1 = Apple::new;
Apple a1 = c1.get();
這就等價于:
Supplier<Apple> c1 = () -> new Apple();
Apple a1 = c1.get();
如果構(gòu)造函數(shù)的簽名是Apple(Integer weight),那么它就適合Function接口的簽名将硝,于是你可以這樣寫:
Function<Integer,Apple> c2 = Apple::new;
Apple a2 = c2.apply(110);
等價于:
Function<Integer,Apple> c2 = (weight) ->new Apple(weight);
Apple a2 = c2.apply(110);
謂詞復(fù)合
謂詞接口包括三個方法:negate恭朗,and和or,讓你可以重用已有的Predicatre來創(chuàng)建更復(fù)雜的謂詞。