Lambda表達式及Stream API

是Lambda表達式符號,其中左側爲接口方法裏的參數,右側爲接口實現類的具體方法,即左側參數是否符合某種斷定條件。

代碼示例圖

Lambda 表達式_Image_1
在這裏插入圖片描述
Lambda 表達式_Image_3
Lambda 表達式_Image_4

Lambda表達式的基礎語法

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.junit.Test;

/*
* 1、Lambda 表達式的基礎語法:Java8中引入了一個新的操做符 "->" 該操做符稱爲箭頭操做符或 Lambda 操做符
 *                             箭頭操做符將 Lambda 表達式拆分紅兩部分:
*
* 左側:Lambda 表達式的參數列表
* 右側:Lambda 表達式中所需執行的功能, 即 Lambda 體
*
* 語法格式一:無參數,無返回值
 *         () -> System.out.println("Hello Lambda!");
*
* 語法格式二:有一個參數,而且無返回值
 *         (x) -> System.out.println(x)
*
* 語法格式三:若只有一個參數,小括號能夠省略不寫
 *         x -> System.out.println(x)
*
* 語法格式四:有兩個以上的參數,有返回值,而且 Lambda 體中有多條語句
 *        Comparator<Integer> com = (x, y) -> {
 *            System.out.println("函數式接口");
 *            return Integer.compare(x, y);
 *        };
*
* 語法格式五:若 Lambda 體中只有一條語句, return 和 大括號均可以省略不寫
 *         Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
*
* 語法格式六:Lambda 表達式的參數列表的數據類型能夠省略不寫,由於JVM編譯器經過上下文推斷出,數據類型,即「類型推斷」
 *         (Integer x, Integer y) -> Integer.compare(x, y);
*
* 上聯:左右遇一括號省
* 下聯:左側推斷類型省
* 橫批:能省則省
*
* 2、Lambda 表達式須要「函數式接口」的支持
* 函數式接口:接口中只有一個抽象方法的接口,稱爲函數式接口。 可使用註解 @FunctionalInterface 修飾
 *              能夠檢查是不是函數式接口
*/
public class TestLambda2 {

    @Test
    public void test1(){
        int num = 0;//jdk 1.7 前,必須是 final

        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello World!" + num);
            }
        };
        r.run();
        System.out.println("-------------------------------");
        Runnable r1 = () -> System.out.println("Hello Lambda!");
        r1.run();
    }
    @Test
    public void test2(){
        Consumer<String> con = x -> System.out.println(x);
        con.accept("Lambda Stream API!");
    }
    @Test
    public void test3(){
        Comparator<Integer> com = (x, y) -> {
            System.out.println("函數式接口");
            return Integer.compare(x, y);
        };
    }
    @Test
    public void test4(){
        Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
    }
    @Test
    public void test5(){
//        String[] strs;
//        strs = {"aaa", "bbb", "ccc"};
        List<String> list = new ArrayList<>();
        show(new HashMap<>());
    }
    public void show(Map<String, Integer> map){
    }
    //需求:對一個數進行運算
    @Test
    public void test6(){
        Integer num = operation(100, (x) -> x * x);
        System.out.println(num);
        System.out.println(operation(200, (y) -> y + 200));
    }
    public Integer operation(Integer num, MyFun mf){
        return mf.getValue(num);
    }
}

Lambda四大內置函數式接口

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.junit.Test;

/*
* Java8 內置的四大核心函數式接口
*
* Consumer<T> : 消費型接口
 *         void accept(T t);
*
* Supplier<T> : 供給型接口
 *         T get();
*
* Function<T, R> : 函數型接口
 *         R apply(T t);
*
* Predicate<T> : 斷言型接口
 *         boolean test(T t);
*
*/
public class TestLambda3 {
    //Predicate<T> 斷言型接口:
    @Test
    public void test4(){
        List<String> list = Arrays.asList("Hello", "atguigu", "Lambda", "www", "ok");
        List<String> strList = filterStr(list, (s) -> s.length() > 3);
        for (String str : strList) {
            System.out.println(str);
        }
    }
    //需求:將知足條件的字符串,放入集合中
    public List<String> filterStr(List<String> list, Predicate<String> pre){
        List<String> strList = new ArrayList<>();
        for (String str : list) {
            if(pre.test(str)){
                strList.add(str);
            }
        }
        return strList;
    }
    //Function<T, R> 函數型接口:
    @Test
    public void test3(){
        String newStr = strHandler("\t\t\t Lambda Stream API   ", (str) -> str.trim());
        System.out.println(newStr);

        String subStr = strHandler("Lambda Stream API", (str) -> str.substring(2, 5));
        System.out.println(subStr);
    }
    //需求:用於處理字符串
    public String strHandler(String str, Function<String, String> fun){
        return fun.apply(str);
    }
    //Supplier<T> 供給型接口 :
    @Test
    public void test2(){
        List<Integer> numList = getNumList(10, () -> (int)(Math.random() * 100));
        for (Integer num : numList) {
            System.out.println(num);
        }
    }
    //需求:產生指定個數的整數,並放入集合中
    public List<Integer> getNumList(int num, Supplier<Integer> sup){
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            Integer n = sup.get();
            list.add(n);
        }
        return list;
    }
    //Consumer<T> 消費型接口 :
    @Test
    public void test1(){
        happy(10000, (m) -> System.out.println("你喜歡吃燒烤,每次消費:" + m + "元"));
    }
    public void happy(double money, Consumer<Double> con){
        con.accept(money);
    }
}

Lambda方法引用與構造器引用

import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import org.junit.Test;

/*
* 1、方法引用:若 Lambda 體中的功能,已經有方法提供了實現,可使用方法引用
 *               (能夠將方法引用理解爲 Lambda 表達式的另一種表現形式)
*
* 1. 對象的引用 :: 實例方法名
*
* 2. 類名 :: 靜態方法名
*
* 3. 類名 :: 實例方法名
*
* 注意:
 *      ①方法引用所引用的方法的參數列表與返回值類型,須要與函數式接口中抽象方法的參數列表和返回值類型保持一致!
 *      ②若Lambda 的參數列表的第一個參數,是實例方法的調用者,第二個參數(或無參)是實例方法的參數時,格式: ClassName::MethodName
*
* 2、構造器引用 :構造器的參數列表,須要與函數式接口中參數列表保持一致!
*
* 1. 類名 :: new
*
* 3、數組引用
*
 *     類型[] :: new;
*
*/
public class TestMethodRef {
    //數組引用
    @Test
    public void test8(){
        Function<Integer, String[]> fun = (args) -> new String[args];
        String[] strs = fun.apply(10);
        System.out.println(strs.length);

        System.out.println("--------------------------");

        Function<Integer, Employee[]> fun2 = Employee[] :: new;
        Employee[] emps = fun2.apply(20);
        System.out.println(emps.length);
    }
    //構造器引用
    @Test
    public void test7(){
        Function<String, Employee> fun = Employee::new;
        BiFunction<String, Integer, Employee> fun2 = Employee::new;
    }
    @Test
    public void test6(){
        Supplier<Employee> sup = () -> new Employee();
        System.out.println(sup.get());
        
        System.out.println("------------------------------------");
        
        Supplier<Employee> sup2 = Employee::new;
        System.out.println(sup2.get());
    }
    //類名 :: 實例方法名
    @Test
    public void test5(){
        BiPredicate<String, String> bp = (x, y) -> x.equals(y);
        System.out.println(bp.test("abcde", "abcde"));
        
        System.out.println("-----------------------------------------");
        
        BiPredicate<String, String> bp2 = String::equals;
        System.out.println(bp2.test("abc", "abc"));
        
        System.out.println("-----------------------------------------");
        
        Function<Employee, String> fun = (e) -> e.show();
        System.out.println(fun.apply(new Employee()));
        
        System.out.println("-----------------------------------------");
        
        Function<Employee, String> fun2 = Employee::show;
        System.out.println(fun2.apply(new Employee()));
    }
    //類名 :: 靜態方法名
    @Test
    public void test4(){
        Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
        
        System.out.println("-------------------------------------");

        Comparator<Integer> com2 = Integer::compare;
    }
    @Test
    public void test3(){
        BiFunction<Double, Double, Double> fun = (x, y) -> Math.max(x, y);
        System.out.println(fun.apply(1.5, 22.2));

        System.out.println("--------------------------------------------------");
        
        BiFunction<Double, Double, Double> fun2 = Math::max;
        System.out.println(fun2.apply(1.2, 1.5));
    }
    //對象的引用 :: 實例方法名
    @Test
    public void test2(){
        Employee emp = new Employee(101, "張三", 18, 9999.99);
        Supplier<String> sup = () -> emp.getName();
        System.out.println(sup.get());
        
        System.out.println("----------------------------------");
        
        Supplier<String> sup2 = emp::getName;
        System.out.println(sup2.get());
    }
    @Test
    public void test1(){
        PrintStream ps = System.out;
        Consumer<String> con = (str) -> ps.println(str);
        con.accept("Hello World!");

        System.out.println("--------------------------------");

        Consumer<String> con2 = ps::println;
        con2.accept("Hello Java8!");

        Consumer<String> con3 = System.out::println;
    }
}

Stream API的操做步驟

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import org.junit.Test;

/*
* 1、Stream API 的操做步驟:
*
* 1. 建立 Stream
*
* 2. 中間操做
*
* 3. 終止操做(終端操做)
*/
public class TestStreamaAPI {

    //1. 建立 Stream
    @Test
    public void test1(){
        //1. Collection 提供了兩個方法  stream() 與 parallelStream()
        List<String> list = new ArrayList<>();
        Stream<String> stream = list.stream(); //獲取一個順序流
        Stream<String> parallelStream = list.parallelStream(); //獲取一個並行流
        //2. 經過 Arrays 中的 stream() 獲取一個數組流
        Integer[] nums = new Integer[10];
        Stream<Integer> stream1 = Arrays.stream(nums);
        //3. 經過 Stream 類中靜態方法 of()
        Stream<Integer> stream2 = Stream.of(1,2,3,4,5,6);
        //4. 建立無限流
        //迭代
        Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2).limit(10);
        stream3.forEach(System.out::println);
        //生成
        Stream<Double> stream4 = Stream.generate(Math::random).limit(2);
        stream4.forEach(System.out::println);
    }
    //2. 中間操做
    List<Employee> emps = Arrays.asList(
            new Employee(102, "李四", 59, 6666.66),
            new Employee(101, "張三", 18, 9999.99),
            new Employee(103, "王五", 28, 3333.33),
            new Employee(104, "趙六", 8, 7777.77),
            new Employee(104, "趙六", 8, 7777.77),
            new Employee(104, "趙六", 8, 7777.77),
            new Employee(105, "田七", 38, 5555.55)
    );
    /*
      篩選與切片
        filter——接收 Lambda , 從流中排除某些元素。
        limit——截斷流,使其元素不超過給定數量。
        skip(n) —— 跳過元素,返回一個扔掉了前 n 個元素的流。若流中元素不足 n 個,則返回一個空流。與 limit(n) 互補
        distinct——篩選,經過流所生成元素的 hashCode() 和 equals() 去除重複元素
     */
    //內部迭代:迭代操做 Stream API 內部完成
    @Test
    public void test2(){
        //全部的中間操做不會作任何的處理
        Stream<Employee> stream = emps.stream()
            .filter((e) -> {
                System.out.println("測試中間操做");
                return e.getAge() <= 35;
            });
        //只有當作終止操做時,全部的中間操做會一次性的所有執行,稱爲「惰性求值」
        stream.forEach(System.out::println);
    }
    //外部迭代
    @Test
    public void test3(){
        Iterator<Employee> it = emps.iterator();

        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
    @Test
    public void test4(){
        emps.stream()
            .filter((e) -> {
                System.out.println("短路!"); // &&  ||
                return e.getSalary() >= 5000;
            }).limit(3)
            .forEach(System.out::println);
    }
    @Test
    public void test5(){
        emps.parallelStream()
            .filter((e) -> e.getSalary() >= 5000)
            .skip(2)
            .forEach(System.out::println);
    }
    @Test
    public void test6(){
        emps.stream()
            .distinct()
            .forEach(System.out::println);
    }
}
相關文章
相關標籤/搜索