程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java8中lambda表達式的使用,以及一些泛型相關

java8中lambda表達式的使用,以及一些泛型相關

編輯:關於JAVA

java8中lambda表達式的使用,以及一些泛型相關。本站提示廣大學習愛好者:(java8中lambda表達式的使用,以及一些泛型相關)文章只能為提供參考,不一定能成為您想要的結果。以下是java8中lambda表達式的使用,以及一些泛型相關正文


語法局部就不寫了,我們直接拋出一個實踐問題,看看java8的這些新特性終究能給我們帶來哪些便當

順帶用到一些泛型編程,一切都是為了簡化代碼

場景:

一個數據類,用於記載職工信息

public class Employee {
    
    public String name;
    public int age;
    public char sex;
    public String time;
    public int salary;

}

我們有一列此類數據

List<Employee> data = Arrays.asList(e1,e2,e3......)

如今有需求:將員工Employee依照姓名的首字母(假定均為英文名)停止分組:

那麼我們要失掉的後果應該是一個Map:char -> List<Employee> 這樣的映射關系

public static Map<Character, List<Employee>> groupByFirstChar(
    List<Employee> data){
        Map<Character, List<Employee>> result = new HashMap<>();
        for(Employee e : data){
            Character c = e.name.charAt(0);
            List<Employee> l = result.get(c);
            if(l == null){
                l = new ArrayList<>();
                result.put(c, l);
            }
            l.add(e);
        }
        return result;
}

代碼並不復雜,很快就可以完成,老板看你效率這麼高,於是說,再依照工資分個組吧,5000以下的,5000~10000的 ...等

也不會太難,將key換一下,稍作邏輯處置即可

public static Map<String, List<Employee>> groupBySalary(List<Employee> data) {
    Map<String, List<Employee>> result = new HashMap<>();
    for (Employee e : data) {
        String key = separate(e.salary);
        List<Employee> l = result.get(key);
        if (l == null) {
            l = new ArrayList<>();
            result.put(key, l);
        }
        l.add(e);
    }
    return result;
} private static String separate(int salary) { if (salary <= 5000) { return "5000以下"; } if (salary <= 10000) { return "5000~10000"; } if (salary <= 20000) { return "10000~20000"; } return "20000以上" }

然後老板又說了,依照員工的入職年份分下組吧。。。

這裡就代碼就不寫了,稍作比擬可以發現,無論怎樣分組,獨一的變化是key值的選取方式,

第一次將Employee的name的第一字母作為key:

Employee e -> e.name.charAt(0)

第二次將Employee的salary依照辦法separat轉換為String作為key:

Employee e -> separate(e.salary):String

以此類推

Employee e -> getYear(e.time):String

現實上第一次也可以將獲取首字母獨自寫成一個辦法

Employee e -> getFirstChar(e.name):Character

為了看起來更美觀,可以講三個辦法的參數都設置成Employee 辦法體就不寫了 這裡只列出參數和前往值

Employee e -> getFirstChar(e) : Character
Employee e -> separate(e) : String
Employee e -> getYear(e) : String

->的右邊為參數,:的左邊為前往值,->的左邊是辦法的簽名

那麼我們自然會想到將變化的局部抽取為參數,其他不變的局部抽取為辦法體,那麼就可以省去那些反復的代碼,顯然變化的局部就是下面列出的,將Employee e轉化成key的辦法,但是我們知道java是不能把辦法作為參數停止傳遞的。不過關於稍有經歷的順序猿來說這並不是問題,我們可以運用接口來完成我們的目的,同時又會遇到另一個問題,以上三個辦法的前往值是不同的,因而我們要用到泛型:

public static <K> Map<K, List<Employee>> groupByKey(List<Employee> data, GetKey<K> getKey){
    Map<K, List<Employee>> result = new HashMap<>();
    for(Employee e : data) {
        K key = getKey.getKey(e);
        List<Employee> l = result.get(key);
        if (l == null) {
            l = new ArrayList<>();
            result.put(key, l);
        }
        l.add(e);
    }
        return result;
}
interface GetKey<K>{
K getKey(Employee e);
}

那麼下面的第一個需求就可以這樣完成

Map<Character, List<Employee>> result = groupByKey(data, new GetKey<Character>() {
            @Override
            public Character getKey(Employee e) {
                e.name.charAt(0);
            }
        });

第二個需求

Map<String, List<Employee>> result = groupByKey(list, new GetKey<String>() {
            @Override
            public String getKey(Employee e) {
                separate(e.salary);
            }
        });

可以發現,我們只需求更改泛型參數和匿名外部類的完成即可,獨一的問題恐怕是這麼寫真實不太美觀,而且很多例行私事的代碼,尤其表現在匿名外部類上。

現實上我們只關懷這個匿名外部類的參數和前往值,其他局部僅僅是語法要求。

java8恰恰為我們提供了很好的方式來防止復雜的例行私事的方式:lambda表達式,以上完成就可以寫成

Map<Character, List<Employee>> resultByFirstChar = groupByKey(list, e -> e.name.charAt(0));
Map<String, List<Employee>> resultBySalary = groupByKey(list, e -> separate(e.salary));

lambda表達式恰恰只表現出我們所關懷的,參數和前往值,同時由於類型推斷,可以省去參數類型,詳細語法這裡就不引見了,網上可以查到很多材料



extra:

假如你對泛型有不錯的理解的話,辦法groupByKey還可以進一步籠統:

public static <K, E> Map<K, List<E>> groupBy(List<? extends E> data, Function<? super E, ? extends K> fun) {
    Map<K, List<E>> result = new HashMap<>();
    for(E e : data) {
        K k = fun.apply(e);
List<E> l = result.get(k); if(l == null) { l = new ArrayList<>(); result.put(k, l); } l.add(e); } return result;
}

我們將Employee這個類也抽取了,益處不言而喻

Function接口是java8新參加的接口:

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}

輸出一個T類型 前往R類型。泛型和函數式編程結合的很不錯,雖然java8的新特性被各種吐槽,但是能帶來益處總是好的,這給了我們更多的選擇。

 

有時間的話會引見stream,java8的另一大利器

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved