Google Code Prettify

2020年11月1日 星期日

Java Lambda: getting started

這篇會整理的是,在傳統語法下及 Lambda 語法,以排序為例進行說明:

在開始說明前,先定義一個類別如下:

@Data
public class Country implements Serializable {
	private String name;       //國名
	private String capital;    //首都
	private String area;       //位於那個洲?
	private int gdp;           //人均GDP
	private int population;    //人口總數
	
	public Country() { }
	
	public Country(String name, String capital, String area, int gdp, int population) {
		this.name = name;
		this.capital = capital;
		this.area = area;
		this.gdp = gdp;
		this.population = population;
	}
}
程式一開始會進建立一個命名為 world 的 List 如下:
List<Country> world = Arrays.asList(		
		new Country("Taiwan", "Taipei", "Asia", 24500, 23500000),
		new Country("Korea", "Seoul", "Asia", 31430, 51709098),
		new Country("Philippines", "Manila", "Asia", 3117, 107225000),
		new Country("Nederland", "Amsterdam", "Europe", 53106, 17291000),
		new Country("Canada", "Ottawa", "America", 47931, 37281000),
		new Country("Australia", "Canberra", "Oceania", 51592, 25220000)
	);
下面的例子就用人口數來排序 world 裡的國家。
  1. 定義實作 Comparator 介面的類別
  2. private class CountryComparator implements Comparator<Country> {
    	@Override
    	public int compare(Country c1, Country c2) {
    		return c1.getPopulation() - c2.getPopulation();
    	}
    }
    
    使用上述的類別規範了比較的方式,程式會如下:
    world.sort(new CountryComparator());
    
  3. 定義實作 Comparator 介面的匿名類別
  4. world.sort(
    	new Comparator<Country>() {
    		@Override
    		public int compare(Country c1, Country c2) {
    			return c1.getPopulation() - c2.getPopulation();
    		}
    	});
    
    這兩種寫法,都是 Java 7 以前的寫法,當這個用來比較的類別很短,又只會使用一次,採用匿名類別可讀性會比較高。
  5. 使用 Lambda
  6. world.sort((c1, c2) -> c1.getPopulation() - c2.getPopulation());
    
    程式怎麼會變得這麼簡單,而且清楚明白,Lambda 怎麼辦到的? Lambda 的使用有一些限制,sort 接受的 Comparator 介面只有一個 method,這是它的重要限制之一! 因為只有一個 method,Lambda expression 就看的出來是要傳入 c1、c2 兩個 Country 類別的物件進入 compare() method,compare() method 在這裡實作為 return c1.getPopulation() - c2.getPopulation()。
  7. 使用「方法引用」
  8. 這是 Lambda 的語法糖,這裡假設我們有靜態導入 java.util.Comparator.comparing (import static java.util.Comparator.comparing)。
    world.sort(comparing(Country::getPopulation));
    
    直接指明要調用 Country 裡的 getPopulation() 的值進行比較。這裡有個疑問,怎麼 Comparator 類別又多出了 comparing 這個 method 了? 而且這個 method 還不只是定義了介面,還實作了 method ! 這是 Java 8 之後才有的,interface 裡也可以實作 method,但是,因為裡面只有一個未實作的 method,仍是合乎 Lambda 的限制,Lambda 知道要使用那個 method。
    有興趣的話,再觀察一下 Comparator 的原始碼,多了不少 static method,上面只比較人口數,事實上我們可以複合比較,如下:
    world.sort(
    	comparing(Country::getArea).thenComparing(Country::getPopulation)
    );
    

沒有留言:

張貼留言