Java 8 之 lambda 表達式簡單使用入門實例代碼

  我這些實例,包含如下:
  Java 8 中 list 和 map 的循環遍歷 - forEach的用法。
  Java 8 中對 list 和 map 集合的過濾 - filter的用法。
  Java 8 中對stream的操作,filter操作。。
  一般都是看到了別人的寫法,或者是編輯器提示你可以這麼寫,你才這麼寫,寫了之後。
  發現;唉,我不一定懂,我是改成這個lambda表達式呢,還是就按之前Java 7 的寫法寫呢?

  現在,我就簡單的把 8 和 7 之間相互的對應起來。
  理論說的再多,你也記不住,記住也沒用。還不如代碼來的實在。
  (說實話,這東西,2014年都出來了,現在我才知道。也不能說才知道,只是說不像for each 循環那樣,天天用。)
  首先,我們需要一個操作對象,爲了貼近實際,咱就不簡單的使用字符串類啥的簡單的類啦,咱自己新建個用戶類,在文章底部。

  下面就要開始搞啦。
  先是獲得個操作集合(map,list)的方法。

/** 
 * 獲得一個list集合 
 */  
private static List<User> getLoopList() {  
    List<User> all = Lists.newArrayList();  
    for (int i = 0; i < 10; i++) {  
        all.add(new User("lxk_" + i, "pwd_" + i));  
    }  
    return all;  
}  

/** 
 * 獲得一個map集合 
 */  
private static Map<Integer, Integer> getLoopMap() {  
    Map<Integer, Integer> map = Maps.newHashMap();  
    for (int i = 0; i < 10; i++) {  
        map.put(i, i);  
    }  
    return map;  
}  

  還有個打印分行符的方法,爲了打印操作方便,咱寫個方法調用的時候,也簡單,也可以重用。不然,你每次 打印個分行符,你還得複製那麼一長串代碼,雖然都是複製,我複製一個方法名快,還是你複製一行代碼快。體現的是代碼封裝重用的思想。。。。呵呵,扯遠啦。。雖然這個方法,看起來很是簡單的樣子。

/** 
 * 打印分行符公共方法 
 */  
private static void println() {  
    System.out.println("___________________我是分行符___________________");  
}  

  獲得了集合之後,就是循環以及操作這個集合啦。簡單對比 7 和 8 的實現不同。
  下面先看看,在循環遍歷的時候的差別:

/** 
 * 測試集合(list,map)循環 
 */  
private static void testLoop() {  
    List<User> list = getLoopList();  
    beforeLoopList(list);  
    lambdaLoopList(list);  

    Map<Integer, Integer> map = getLoopMap();  
    beforeLoopMap(map);  
    lambdaLoopMap(map);  
}  

/** 
 * 以前循環一個集合,for和foreach循環 
 */  
private static void beforeLoopList(List<User> list) {  
    for (User user : list) {  
        System.out.println(user.toString());  
    }  
    println();  
}  

/** 
 * 使用lambda循環一個集合 
 */  
private static void lambdaLoopList(List<User> list) {  
    //三行循環效果相同  
    //list.forEach(user -> System.out.println(user.toString()));  
    //list.forEach(user -> System.out.println(user));//下面一行代碼就是簡寫形式  
    list.forEach(System.out::println);  
    println();  
}  

/** 
 * Java 7 的map的遍歷 
 */  
private static void beforeLoopMap(Map<Integer, Integer> map) {  
    System.out.println("Java 7 遍歷map");  
    for (Map.Entry<Integer, Integer> entry : map.entrySet()) {  
        System.out.println("k " + entry.getKey() + " v " + entry.getValue());  
    }  
    for (Integer key : map.keySet()) {  
        System.out.println("k " + key);  
    }  
    for (Integer value : map.values()) {  
        System.out.println("v " + value);  
    }  
    println();  
}  

/** 
 * Java 8 的map的遍歷 
 */  
private static void lambdaLoopMap(Map<Integer, Integer> map) {  
    System.out.println("Java 8 遍歷map");  
    map.forEach((k, v) -> System.out.println("k " + k + " v " + v));  
    println();  
}  

  Java 8 的for each 變成啦 forEach ,就是上面代碼所展示的那樣。
前面的user是自己聲明的變量, -> 這個箭頭後面的呢就是對這個變量的操作。後面要是多行代碼的話,就的弄個大括號,括起來。
  沒有註釋的那行代碼,看着就是相當的精煉。。。。
  左邊是容器(可以是類名,實例名),中間是”::”,右邊是相應的方法名。

  上面循環遍歷的姿勢會了,那麼就想在循環遍歷的時候,順帶操作修改一下集合內容,
  下面看循環遍歷操作集合的時候的差別

/** 
 * 測試循環的時候,順帶操作集合中的內容。 
 */  
private static void testLoopOperate() {  
    List<User> list = getLoopList();  
    lambdaOperateList(list);  

    Map<Integer, Integer> map = getLoopMap();  
    lambdaOperateMap(map);  
}  

private static void lambdaOperateList(List<User> list) {  
    System.out.println("對list集合進行操作:user's name + “_1” ");  
    //list.forEach(user -> user.setName(user.getName() + "_1"));  
    list.forEach(user -> {  
        String name = user.getName();  
        user.setName(name + "_1");  

        //在循環的時候,不能修改list結構(包括新增和刪除).  
        //不然會出現此異常:Exception in thread "main" java.util.ConcurrentModificationException  
        //if(user.getPwd().contains("1")){  
        //    list.remove(user);  
        //}  
        //if(user.getPwd().contains("1")){a  
        //    list.add(new User("10","10"));  
        //}  
    });  
    //操作完,循環輸出一下,看下是否操作OK。  
    list.forEach(System.out::println);  
    println();  
}  

private static void lambdaOperateMap(Map<Integer, Integer> map) {  
    System.out.println("對map集合進行操作:map's value + 10 ");  
    map.forEach((k, v) -> {  
        v = v + 10;  
        map.put(k, v);//更新。  

        //在循環的時候,不能修改map結構(包括新增和刪除).  
        //不然會出現此異常:Exception in thread "main" java.util.ConcurrentModificationException  
        //if(k == 1){  
        //    map.remove(k);  
        //}  
        //if(k == 9){  
        //    map.put(10,10);//添加,  
        //}  
    });  
    lambdaLoopMap(map);  
    println();  
}  

  注意,上面我說的那些個異常的情況,那些你在Java 7 裏面循環的時候,要是也這麼幹,也是會出異常的。
看上面代碼的運行結果:
這裏寫圖片描述
  Java 8 還有個 stream ,流,這個流不是咱一般的文件流的那個流。
先看這個stream裏面的filter方法:對操作集合,按某個條件進行過濾。

/** 
 * 測試collection.stream().filter() 
 */  
private static void testStreamFilter() {  
    List<User> list = getLoopList();  
    System.out.println("對集合進行過濾:user name 包含 1 的用戶");  
    List<User> filtered = list.stream().filter(s -> s.getName().contains("1")).collect(Collectors.toList());  
    filtered.forEach(user -> System.out.println(user.toString()));  
    println();  
}  

  上面代碼的運行結過:
這裏寫圖片描述
  一般的集合類,就是咱常用的list的實現類,都可以直接調用這個方法。hashmap之類的除外。
  說到原理:那就是在Collection類裏面有stream()這個方法,所以,一般的繼承的這個類的類都可以直接調用stream(),獲得流。繼而進行下一步操作。
  Java 8 裏面,對接口,也就是interface,進行了擴展,以前,咱只能簡單的聲明一些方法,並不能去實現這些方法,要實現,那隻能到抽象類裏面去實現。
  現在接口裏面也可以實現方法啦,只是要在這個方法的前面加一個關鍵字:default。。。。這個stream()就是這麼實現的。
  關於這個流Stream,Java 8 裏面有個並行流的概念,這個就大概瞭解下。
  流操作可以是順序的,也可以是並行的。順序操作通過單線程執行,而並行操作則通過多線程執行。
  這個升級就是充分的利用計算機的多核的高科技,大家都這麼說,我也就這麼說一下咯。至於兩者的差別。
  看下面的實驗現象吧;
  Java 8 lambda stream forEach parallel 等循環與Java 7 for each 循環耗時測試
  這個鏈接裏面展示了串行和並行同時去打印一個集合的元素的時候的差別。可以簡單看下。
  關於filter 用法,就是裏面就是個過濾這個集合的條件,必須是返回true 或者false。纔可以。不然就OK啦。

/** 
 * 測試collection.stream().map() 
 */  
private static void testStreamMap() {  
    List<User> list = getLoopList();  
    System.out.println("對集合進行操作:user name + “1” ");  
    List<String> nameList = list.stream().map(User::getName).collect(Collectors.toList());  
    nameList.forEach(System.out::print);  
    println();  
}  

  運行結果:
這裏寫圖片描述
  這個map也算是操作集合數據,

  下面再看個簡單的例子:

/** 
 * 測試用法,稍複雜的串行操作。 
 * 過濾空值;去重;排序;循環輸出。 
 */  
private static void testNumber() {  
    List<Integer> integers = Arrays.asList(1, 3, null, 8, 7, 8, 13, 10);  
    integers.stream().filter(Objects::nonNull).distinct().sorted().forEach(System.out::println);  
}  

  運行結果:
這裏寫圖片描述
  代碼操作中使用的model類

package com.lxk.model;  

/** 
 * 用戶model 
 * <p> 
 * Created by lxk on 2017/8/31 
 */  
public class User {  
    private String name;  
    private String pwd;  


    public User() {  
    }  

    public User(String name, String pwd) {  
        this.name = name;  
        this.pwd = pwd;  
    }  

    public String getName() {  
        return name;  
    }  

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

    public String getPwd() {  
        return pwd;  
    }  

    public void setPwd(String pwd) {  
        this.pwd = pwd;  
    }  

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

  這個類,很簡單,也就是一個用戶名和密碼兩個字符串的屬性,然後就再有一個toString方法。
  哦,還有2個構造函數,你要問爲什麼這有2個構造函數嗎?
  我爲啥寫那個不帶參數的構造函數呢?因爲,這個不帶參數的構造函數 ,你不用,但是,一般的spring,等框架是要用的。咱還是不要省了。



  這個世界上沒有知識是學不會的,不是嗎?如果一開始學不會,就可以把問題細化分解,然後學習更基本的知識。最後,所有問題都能變得和1+1=2一樣簡單,我們需要的只是時間。好了,最後給大家推薦一個學習Java的好網站JAVA自學網站–how2j.cn

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章