Java8新特性

Lambda表達式

示例

static List<Employee> employees = Arrays.asList(
            new Employee("張三", 12, 5000),
            new Employee("李四", 20, 6000),
            new Employee("王二", 37, 4000),
            new Employee("周五", 19, 3000),
            new Employee("今天", 80, 9000)
    );

public interface Mypredict<T> {
    boolean test(T t);
}
@Test
public void test(){
     List<Employee> eps = dodo(employees, (e) -> e.getWage() > 500);
     eps.forEach(System.out::println);
}
public static List<Employee> dodo(List<Employee> list, Mypredict<Employee> me) {
        List<Employee> employees = new ArrayList<>();
        for (Employee employee : list) {
            if (me.test(employee)) {
                employees.add(employee);
            }
        }
        return employees;
 }
  • 語法格式

    • 1.無參數(shù)無返回值,Lambda箭頭操作符' -> ',左邊表示參數(shù)列表,右邊為函數(shù)式結(jié)構(gòu)的實現(xiàn)@FunctionalInterface的實現(xiàn),類比匿名內(nèi)部類
    @FunctionalInterface
    public interface LamTest {
        public void T();
    }
    
    @Test
    public void test(){
    LamTest lamTest=()->System.out.println("lambda的無參數(shù)無返回格式");
            lamTest.T();
    }
    
    • 2.一個參數(shù),無返回值
    @FunctionalInterface
    public interface LamTest {
        public void T(String str);
    }
    
    @Test
    public void test(){
     LamTest lamTest=(x)->System.out.println(x);
            lamTest.T("hello");
    }
    
    • 3.多個參數(shù),帶有返回值
    @FunctionalInterface
    public interface LamTest {
        public StringBuilder T(String str,String str2);
    }
    @Test
    public void test(){
    LamTest lamTest=(x,y)->{
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append(x).append(y);
                return stringBuilder;
            };//有多條語句是使用大括號括起來,使用return返回目標值
    LamTest lamTest1 = (x, y) -> new StringBuilder().append(x).append(y);//單條語句時,可以省略return
            System.out.println(lamTest.T("zhou","真"));
            System.out.println(lamTest1.T("zhou","假"));
    }
    
    • 注意事項:
      • lambda表達式與匿名內(nèi)部類一樣,可以調(diào)用,但是不可以對局部變量進行改變,雖沒有顯式聲明,但是java8中默認將表達式中使用的局部變量設(shè)置為了final。
      • @FunctionalInterface是用來檢驗是否為函數(shù)式接口(只存在一個抽象方法的接口)
      • lambda表達式不需要聲明參數(shù)類型,jvm使用"類型推斷"可自動判斷參數(shù)類型,如果聲明,則所有參數(shù)需要聲明類型
      • 當參數(shù)列表只有一個參數(shù)傳入時候,可以省略括號,但不建議這樣做

    lambda表達式與匿名內(nèi)部類示例

    ? 函數(shù)式接口

    @FunctionalInterface
    public interface Mypredict<T> {
        boolean test(T t);
    }
    
public void test() {
        //單條語句帶返回值
        dodo(employees, (e) -> e.getWage() > 5000).stream().forEach(System.out::println);
        //多條語句帶返回值
        dodo(employees, (e) -> {
            boolean b = e.getWage() > 5000;
            return b;
        }).stream().forEach(System.out::println);
        //匿名內(nèi)部類
        dodo(employees, new Mypredict<Employee>() {
            @Override
            public boolean test(Employee employee) {
                return employee.getWage()>5000;
            }
        }).stream().forEach(System.out::println);
    }
  //具體方法
    public static List<Employee> dodo(List<Employee> list, Mypredict<Employee> me) {
        List<Employee> employees = new ArrayList<>();
        for (Employee employee : list) {
            if (me.test(employee)) {
                employees.add(employee);
            }
        }
        return employees;
    }

Java8提供的四個核心函數(shù)式接口:

  1. Comsumer<T> : 消費型接口

    ? void accept(T t);

  2. Supplier<T>: 供給型接口

    ? T get();

  3. Functional<T,R> : 函數(shù)型接口

    ? R apply(T t);

  4. Predicate<T>: 斷言型接口

    ? boolean test(T t);

lambda表達式方法引用

如果lambda表達式的內(nèi)容已經(jīng)有現(xiàn)有方法實現(xiàn),可以使用"方法引用",調(diào)用現(xiàn)有的方法

語法格式:

  1. 對象::實例方法名

            //before
            Consumer com=x->System.out.println(x);
            com.accept("hello");
            //對象::實例方法名
            PrintStream ps = System.out;
            Consumer con = ps::println;//System.out::println
            con.accept("hello");
    
  1. 類::靜態(tài)方法名

          //before
            Comparator<Integer> comparator = (x, y) -> Integer.compare(x,y);
            System.out.println(comparator.compare(1, 3));
            //類::靜態(tài)方法名
            Comparator<Integer> comparator1 = Integer::compareTo;
            comparator1.compare(1, 3);
    
  2. 類::實例方法名(要求參數(shù)列表中的第一個參數(shù)需要是方法的調(diào)用者,另一個參數(shù)為被調(diào)用的方法所需的參數(shù)傳入)

         //before
            BiPredicate<String, String> biPredicate = (x, y) -> x.equals(y);
            System.out.println(biPredicate.test("heel", "sdad"));
            //after
            BiPredicate<String, String> biPredicate1 = String::equals;
            System.out.println(biPredicate.test("heel", "sdad"));
    
  3. 構(gòu)造器引用(構(gòu)造器的參數(shù)列表需要與函數(shù)式接口中的抽象方法列表一致)

    無參時:

     Supplier<Employee> supplier = Employee::new;
      System.out.println(supplier.get().getClass().getName());
    

    有參時(需要目標類提供帶參構(gòu)造器):

         //before
            Function<String,Employee> employeeFunction=(x)->new Employee(x);
            System.out.println(employeeFunction.apply("name"));
            //構(gòu)造引用
            Function<String, Employee> employeeFunction1 = Employee::new;
            System.out.println(employeeFunction1.apply("TTTT"));
    
  1. 數(shù)組引用:

      //before
            Function<Integer, String[]> function = (x) -> new String[x];
            System.out.println(function.apply(6).length);
            //數(shù)組引用
            Function<Integer, String[]> function1 = String[]::new;
            ps.println(function1.apply(10).length);
    

Stream()API

示例

static List<Employee> employees = Arrays.asList(
            new Employee("張三", 12, 5000),
            new Employee("李四", 20, 6000),
            new Employee("王二", 37, 4000),
            new Employee("周五", 19, 3000),
            new Employee("今天", 80, 9000)
    );
@Test
public void test(){
    employees.stream().filter((e) -> e.getWage() > 7000).forEach(System.out::println);
}
  • Stream流的創(chuàng)建:
  1. 通過Collection系列的集合創(chuàng)建:

     List<String> a = new ArrayList<String>();
            a.add("aa");
            a.add("bb");
            a.add("cc");
            Stream stream =a.stream();
    
  1. 通過Arrays中的靜態(tài)方法stream()獲取數(shù)組流

    Stream<String> stream1 = Arrays.stream(new String[10]);
    
  2. 通過Stream中的靜態(tài)方法of:

    Stream<String> stream1 = Arrays.stream(new String[10]);
    
  3. 創(chuàng)建無限流

    1. 迭代
    Stream<Integer> stream3 = Stream.iterate(0, x -> x + 2);
    
    1. 生成
     Stream<Double> stream4 = Stream.generate(Math::random);//方法引用
     Stream<Double> stream5 = Stream.generate(() -> Math.random());//方法調(diào)用
    
  • Stream流的中間操作(多個中間操作可稱為流水線操作,只有當終止操作存在時才會觸發(fā)中間操作,“惰性求值

    ”),生成新的流

    • filter(Predicate p)
    • distinct()篩選,去除掉重復元素(需要在源元素中重寫hashcode()和equals()操作)
    • limit(n)取流的前n個元素
    • skip(n)與limit()互補,丟棄流的前n個元素,當流中元素不足n時,返回空流。
  • Stream流中的map映射(將流中的每一個元素變成一個新的流,再將這些流放入一個流Stream<Stream<T>>):

    @Test
    public void T{
    List<String> a = new ArrayList<String>();
            a.add("aaa");
            a.add("bbb");
            a.add("ccc");
          Stream<Stream<Character>> streamStream= a.stream().map(Test::d);
            streamStream.forEach(e -> {
                e.forEach(System.out::println);
            });
    }
    public static Stream<Character> d(String string) {
            List<Character> characters = new ArrayList<>();
            for (Character c : string.toCharArray()) {
                characters.add(c);
            }
            return characters.stream();
        }
    
  • Stream流中的flatmap映射(將所有的元素按照需求變更后重新放置再一個流中Stream<T>):

    
    @Test
    public void T{
    List<String> a = new ArrayList<String>();
            a.add("aaa");
            a.add("bbb");
            a.add("ccc");
        
    Stream<Character> characterStream=a.stream().flatMap(e->{
               List<Character> characters = new ArrayList<>();
               for (Character character : e.toCharArray()) {
                   characters.add(character);
               }
               return characters.stream();
           });
           characterStream.forEach(x->System.out.println(x));
    }
    
  • Stream的查找與匹配

    1. allMatch--檢查是否匹配所有元素
    2. anyMatch--檢查是否至少匹配一個元素
    3. noneMatch--檢查是否沒有匹配所有元素
    4. findFirst--返回第一個元素
    5. count--返回流中的元素的總個數(shù)
    6. max--返回流中的最大值
    7. min--返回流中最小值
  • Strem規(guī)約(通過將流中的元素反復結(jié)合返回一個T/Optional<T>)

    • reduce(T iden,BinaryOperator b)
    //計算平方和
    List<Integer> nums = new ArrayList<>();
            nums.add(2);
            nums.add(4);
            nums.add(3);
            nums.add(7);
            Integer reduce = nums.stream().reduce(0, (x, y) -> x + y*y);//0相當于初始值x
            System.out.println(reduce);
    
    • reduce(BinaryOperator b)
    //計算總和 
    Optional<Integer> reduce1 = nums.stream().reduce(Integer::sum);
            System.out.println(reduce1);
    
  • Stream的收集collect(將流轉(zhuǎn)換成其他形式,接受一個Collector接口的實現(xiàn)(一般使用Collectors工具類及其靜態(tài)方法)用于給Stream中元素做匯總)

  • Stream的分組,通過collect(Collectors.groupingBy())來進行分組,返回一個Map類型

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容