java8之lambda表達式看這一篇就夠了
java8增加了許多新特性,其中lambda表達式可以說為最重要的特性之一,本文將從如下幾個方面來學習lambda:
1、lambda表達式的基本定義
2、lambda表達式的語法
3、lambda表達式基本示例
一、何為lambda表達式?
簡單點說lambda為一種匿名函數,它既沒有名字也沒有聲明的方法、訪問修飾符和返回值等。它允許將函數作為方法的參數進行傳遞。
二、基本語法:lambda通常包含如下幾種書寫方式
() -> expression
() -> { statement }
() -> { statements }
(arg1,arg2) -> { statement }
(Type arge1,Type arge2) -> { statement }
三、jdk內置的函數式接口以及基本示例介紹
jdk內置了如下四大函數式接口,在java.util.function包下可以找到:
1、Function 接收一個參數類型 T , 返回類型 R ,適用於包裝、修改等操作
@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; } }
下面的代碼演示了如何獲取一個學生的所有名字:
public static void main(String[] args) { Student student1 = new Student("a",11); Student student2 = new Student("b",12); Student student3 = new Student("c",21); Student student4 = new Student("d",1); List<Student> students = new ArrayList <>(); students.add(student1); students.add(student2); students.add(student3); students.add(student4); List < String > names = filterStudent(students , student -> student.getName()); names.forEach((name)-> System.out.println(name)); //輸出結果:a b c d } public static <T,R> List<R> filterStudent(List<T> list, Function<T,R > function){ List<R> names = new ArrayList <>(); for (T t : list) { names.add(function.apply(t)); } return names; }
2、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); }; } }
適用於遍歷,最典型的 foreach 示例:
1 List<String> list = new ArrayList <>(); 2 list.add("a"); 3 list.add("b"); 4 list.add("c"); 5 list.add("d"); 6 list.forEach((str)->System.out.println(str)); 7 //直接調用類的方法進行輸出 8 list.forEach(System.out::println); 9 10 list.forEach((str)->{ 11 //若為一個對象,可以進行其余的保存、更新等操作 12 System.out.println(str); 13 });
3、Predicate 接受一個參數T ,返回boolean,適用於判斷過濾等操作
1 @FunctionalInterface 2 public interface Predicate<T> { 3 4 boolean test(T t); 5 6 default Predicate<T> and(Predicate<? super T> other) { 7 Objects.requireNonNull(other); 8 return (t) -> test(t) && other.test(t); 9 } 10 11 12 default Predicate<T> or(Predicate<? super T> other) { 13 Objects.requireNonNull(other); 14 return (t) -> test(t) || other.test(t); 15 } 16 17 18 static <T> Predicate<T> isEqual(Object targetRef) { 19 return (null == targetRef) 20 ? Objects::isNull 21 : object -> targetRef.equals(object); 22 } 23 }
下面的代碼演示了 Predicate 接口的基本用法:
1 public static void main(String[] args) { 2 Student student1 = new Student("a",11); 3 Student student2 = new Student("b",12); 4 Student student3 = new Student("c",21); 5 Student student4 = new Student("d",1); 6 List<Student> students = new ArrayList <>(); 7 students.add(student1); 8 students.add(student2); 9 students.add(student3); 10 students.add(student4); 11 List < Student > students1 = testStudent(students , student -> student.getAge() > 11); 12 students1.forEach(student -> System.out.println(student.getName())); 13 //輸出結果:b c 14 } 15 16 public static <T> List<T> testStudent(List<T> list , Predicate<T> function){ 17 List<T> newList = new ArrayList <>(); 18 for (T t : list) { 19 if(function.test(t)){ 20 newList.add(t); 21 } 22 } 23 return newList; 24 }
4、Supplier 無參數,返回一個結果
1 @FunctionalInterface 2 public interface Supplier<T> { 3 4 T get(); 5 6 }
從上面的四個函數式接口中我們可以總結出如下幾點:
1、函數式接口一般都有 @FunctionalInterface 註解標識,但是此註解並非強制需要,如果不標註的話編譯器將無法識別只能擁有一個未實現的方法
2、函數式接口之接受唯一的 public 方法 ,但是允許有 default 方法 、靜態方法以及 父類Object的方法(如果聲明第二個public方法會直接報錯,大家可以試一下)。
函數式接口的使用一般會配合 java中Stream Api進行使用,下篇文章將會講解java中Stream流的處理。
java8之lambda表達式看這一篇就夠了