天天看點

java8 新特性--lambda表達式入門學習

1 概述

最近在使用java做一些資料處理,發現使用java8新特性很好用,看着也很高大上,下面進行學習下.

2 初體驗

需求:按照字元長長度進行排序
  1. 原來的方式:Comparator() --> 匿名内部類
@Test
    public void compareLength1(){
        Comparator<String> comparator = new Comparator<String>() {
            public int compare(String o1, String o2) {
                return Integer.compare(o1.length(),o2.length());
            }
        };
        TreeSet<String> set = new TreeSet<>(comparator);
        set.add("a");
        set.add("bb");
        set.add("ccc");
        for (String s : set) {
            System.out.println(s);
        }
    }
           
  1. lambda表達式
@Test
    public void compareLength2(){
        Comparator<String> comparator = (x,y)-> Integer.compare(x.length(),y.length());
        TreeSet<String> set = new TreeSet<>(comparator);
        set.add("a");
        set.add("bb");
        set.add("ccc");
        for (String s : set) {
            System.out.println(s);
        }
    }
           

相信大家可以有一個簡單的認識了,直覺上來看寫法上更加簡潔了,看着更高大上了。肯定不止這些哈,用起來肯定更加友善,加快開發效率。下面我們繼續通過例子進行學習。

3 進一步認識lambda表達式

大家應該知道,使用sql語句可以很友善的進行各種條件過濾,選取TopN等需求,也是我們經常用到的,而在java中實作這些共能,在java8之前是沒有那麼多算子,寫法上也是相對複雜的。下面我們繼續lambda表達式的學習,後面也會學習一些其他的特性,Stream Api等。

3.1 需求:按指定條件過濾
  • 實體類User
public class User {
    private int id;
    private String name;
    private int age;
    private Double salary;

    public User(int id, String name, int age, Double salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }
}

           
  1. 擷取年齡小于 35 的人員資訊
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 按條件過濾
 */
public class LambdaTrain2 {

    List<User> emps = Arrays.asList(
            new User(1, "張三", 18, 9999.9),
            new User(2, "李四", 59, 7777.7),
            new User(3, "王五", 28, 3333.33),
            new User(4, "趙六", 8, 8888.88),
            new User(5, "田七", 38, 5555.55)
    );
    //擷取年齡小于 35 的人員資訊
    @Test
    public void filterUser(){
        List<User> list1 =new ArrayList<>();
        for (User user : emps) {
            if (user.getAge()<35) {
                list1.add(user);
            }
        }
        for (User user : list1) {
            System.out.println(user);
        }
    }
           
  1. 現在需求變化,要求擷取薪水大于5000的人員資訊
//擷取薪水大于5000的人員資訊
    @Test
    public void filterUser1(){
        List<User> list1 =new ArrayList<>();
        for (User user : emps) {
            if (user.getSalary()>5000.0) {
                list1.add(user);
            }
        }

        for (User user : list1) {
            System.out.println(user);
        }
    }
           

小結: 目前功能是實作了但是大家有沒發現,這兩個方法其中 最主要的差別就是

if()

語句中的判斷條件,其他的都是一樣的,是以說這樣子寫并不是最好的。備援性太高。

3.2 優化:
  1. 政策設計模式
  • 實作自定義過濾接口
public interface MyFilter<T> {

    public boolean filter(T t);

}
           
  • 設計根據年齡進行過濾FilterWithAge
public class FilterWithAge implements MyFilter<User> {
    @Override
    public boolean filter(User user) {
        return user.getAge()<35;
    }
}
           
  • 設計根據薪水進行過濾FilterWithSalary
public class FilterWithAge implements MyFilter<User> {
    @Override
    public boolean filter(User user) {
        return user.getSalary()>5000.0;
    }
}
           
  • 功能實作
//emps就是上面的list
//優化方式一:政策設計模式

    public List<User> filterUser2(List<User> userList, MyFilter<User> myFilter){
        List<User> list =new ArrayList<>();
        for (User u: userList){
            if (myFilter.filter(u)){
                list.add(u);
            }
        }
        return list;
    }
    @Test
    public void test(){
        //按照年齡小于35過濾
        List<User> users = filterUser2(emps, new FilterWithAge());
        for (User user:users){
            System.out.println(user);
        }

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

        //按照薪水大于
        List<User> users1 = filterUser2(emps,new FilterWithSalary());
        for (User user:users1){
            System.out.println(user);
        }
    }
           

小結: 個人了解哈上面展現了一種面向接口程式設計,是一種優化方式,減少了備援代碼,但是個人感覺也挺繁瑣的又要寫接口,又要為每種過濾條件建立一個類…還是挺複雜的。下面我們繼續優化。

  1. 匿名内部類
//優化方式二:匿名内部類
    @Test
    public void test2(){
        List<User> users = filterUser2(emps, new MyFilter<User>() {
            @Override
            public boolean filter(User user) {
                return user.getId()>2;
            }
        });
        for (User user:users){
            System.out.println(user);
        }
    }
           

小結: 到這來感覺應該是很簡潔了,代碼看着也很高大上,哈哈哈。但是匿名内部類讓人看着就不是很好了解,

java8之後我們提供了更加簡潔的方式,下面進行我們的主題, java8新特性的使用。

  1. Lambda 表達式
//優化方式三:Lambda 表達式
    @Test
    public void test3(){
        //調用上面寫的方法filterUser2()
        List<User> users = filterUser2(emps, x -> x.getAge() < 35);
        //調用提供的forEach方法
        users.forEach(System.out::println);
    }
           

小結: 上面就使用到了我們的Lambda表達式,是不是看着更簡潔,不用寫匿名内部類了哈,後面我們會講解為什麼可以這樣寫,其實就是函數式程式設計,實作内部已經實作的接口,就是一種文法糖.最後我們看看更簡潔的寫法。

也是我們後續所學的Stream API。

4. Stream API

//優化方式四:Stream API
    //前面我們都是在調已經寫好的filterUser2方法,下面我們不使用試試看哈
    @Test
    public void test4(){

        //按年齡賽選
        emps.stream()
            .filter(x-> x.getAge() < 35)
            .forEach(System.out::println);

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

        //按id篩選,排序,選top3
        emps.stream()
            .filter(x-> x.getId()>2)
            .sorted((a,b)->b.getId()-a.getId()) //預設是升序
            .limit(3)
            .forEach(System.out::println);
    }
           

總結: 你還不想學嗎?寫法夠裝逼嗎?學過scala的同學應該很熟悉,這種寫法跟scala好像啊。看到這裡我個人的想法的,牛批,反正我是想學!