JAVA8新特性 Lambda表達式、雙冒號、streamm詳解


Lambda 允許把函數作為參數傳遞進方法中。

不是每個接口都可以縮寫成 Lambda 表達式。只有那些函數式接口(Functional Interface)才能縮寫成 Lambda 表示式。

所謂函數式接口(Functional Interface)就是只包含一個抽象方法的聲明。
只要接口中僅僅包含一個抽象方法,我們就可以將其改寫為 Lambda 表達式。為了保證一個接口明確的被定義為一個函數式接口(Functional Interface),我們需要為該接口添加注解:@FunctionalInterface。這樣,一旦你添加了第二個抽象方法,編譯器會立刻拋出錯誤提示。

Lambda表達式的重要特征:
  可選類型聲明:不需要聲明參數類型,編譯器可以統一識別參數值。
  可選的參數圓括號:一個參數無需定義圓括號,但多個參數需要定義圓括號。
  可選的大括號:如果主體包含了一個語句,就不需要使用大括號。
  可選的返回關鍵字:如果主體只有一個表達式返回值則編譯器會自動返回值,大括號需要指定明表達式返回了一個數值。

變量作用域
  lambda 表達式只能引用標記了 final 的外層局部變量,這就是說不能在 lambda 內部修改定義在域外的局部變量,否則會編譯錯誤。

Lambda表達式的基本語法:

(parameters) -> expression  或  (parameters) ->{ statements; }

Lambda小程序,遍歷 List 集合

String[] array = {"a","b","c"};
List<String> list = Arrays.asList(array);
 
System.out.println("方式一:原始方式");
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}
 
System.out.println("方式二:增強 for 循環");
for (String s : list) {
    System.out.println(s);
}
 
System.out.println("方式三:lambda 表達式");
list.forEach( e -> System.out.println(e) );
 
System.out.println("方式四:lambda 表達式");
list.forEach( (e) -> {System.out.println(e);} );
 
System.out.println("方式五:lambda 表達式 之 靜態方法引用");
list.forEach(System.out::println);

Lambda 小程序,使用 Lambda 表達式實現匿名內部類

System.out.println("方式一:匿名內部類實現 Runnable接口 run 方法,並使用多線程運行");
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello world !");
    }
}).start();
 
System.out.println("方式一:Lambda 實現 Runnable接口,並使用多線程運行");
new Thread(() -> System.out.println("Hello world !")).start();
 
System.out.println("方式二:匿名內部類實現 Runnable接口 run 方法");
Runnable r1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello world !");
    }
};
r1.run();
 
System.out.println("方式二:Lambda 實現 Runnable接口");
Runnable r2 = () -> System.out.println("Hello world !");
r2.run();

真實應用示例(forEach):

// 遍歷比較
Set<DeptItem> itemList = entity.getRppDeptItem();
if(entity.getDatasource().equals(DeptDateSourceEnum.nc.getCode())){
    itemList.forEach(item->{
        if(item.getNcid() == null && item.getPersistStatus().equals(PersistStatus.ADDED)){
            throw new RuntimeException("來源NC部門不允許在主數據新增崗位" );
        }
    });
}

雙冒號 ::

雙冒號運算符在Java 8中被用作方法引用,方法引用是與 lambda 表達式相關的一個重要特性。它提供了一種不執行方法的方法。為此,方法引用需要由兼容的函數接口組成的目標類型上下文。

使用lambda表達式會創建匿名方法, 但有時候需要使用一個lambda表達式只調用一個已經存在的方法(不做其它), 所以這才有了方法引用!

以下是Java 8中方法引用的一些語法:
  靜態方法引用語法:classname::methodname 例如:Person::getAge
  對象的實例方法引用語法:instancename::methodname 例如:System.out::println
  對象的超類方法引用語法: super::methodname
  類構造器引用語法: classname::new 例如:ArrayList::new
  數組構造器引用語法: typename[]::new 例如: String[]:new

簡要:https://www.cnblogs.com/maohuidong/p/11527681.html

詳細:https://blog.csdn.net/zhoufanyang_china/article/details/87798829

真實應用示例(stream、::):

// list轉換成數組
List<String> list = Arrays.asList("a","b","c");
String[] arrays = list.stream().toArray(String[]::new);
for (String array : arrays) {
    System.out.println(array);
}

Stream

采用java8 lambda表達式 實現 java list 交集 並集 差集 去重復並集

Java 8 中的 Stream 是對集合(Collection)對象功能的增強,使用的是函數式編程模式,它可以對集合進行鏈狀流式的操作,它專注於對集合對象進行各種非常便利、高效的聚合操作(aggregate operation),或者大批量數據操作 (bulk data operation)。Stream API 借助於同樣新出現的 Lambda 表達式,極大的提高編程效率和程序可讀性。

流的執行:
當存在終端操作時,中間操作操作才會被執行。

入門看我:https://www.jianshu.com/p/11c925cdba50

一般詳細:https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/index.html#icomments

非常詳細:https://juejin.im/post/5cc124a95188252d891d00f2

 真實應用示例(stream.map):

// 小寫字母轉換為大寫字母
List<String> collected1 = Arrays.asList("alpha","beta");
collected1 = collected1.stream().map(string -> string.toUpperCase()).collect(Collectors.toList());
System.out.println(collected1);

 真實應用示例(stream.map):

// string轉換為list
String ids = "1,2,3     ,4,5";
List<Long> listIds = Arrays.asList(ids.split(",")).stream().map(e -> Long.valueOf(e.trim())).collect(Collectors.toList());
System.out.println(listIds);

 真實應用示例(stream.map):

// 獲取到所有商品ID
// List<ProductSkuImageDto> resultList = updateProductSkuValues(addedList, modifiedList, deletedList);
// 寫法一
List<String> productIdsList = resultList.stream().map(ProductSkuImageDto::getProductId).collect(Collectors.toList());
// 寫法二
List<String> productIdsList = resultList.stream().map(e -> e.getProductId()).collect(Collectors.toList());

 真實應用示例(stream.forEach):

// 遍歷值放到map中
protected Map<String, GoodsBomDto> getBomInfos(Set<String> parentGoodsIds){
    if(CollectionUtils.isEmpty(parentGoodsIds)){
        return new HashMap<>(0);
    }
    List<GoodsBomDto> goodsBomDtos = goodsBomApi.goodsBomByParentGoodId(String.join(",", parentGoodsIds)).getBody();
    if(CollectionUtils.isEmpty(goodsBomDtos)){
        return new HashMap<>(0);
    }
    Map<String, GoodsBomDto> parentGoodsId_bomMap = new HashMap<>(goodsBomDtos.size());
    goodsBomDtos.stream().forEach(goodsBomDto -> parentGoodsId_bomMap.put(goodsBomDto.getParentGoodsId(), goodsBomDto));
    return parentGoodsId_bomMap;

 真實應用示例(stream.forEach):

// 給實體里面的數字,設置一個值
protected void set_Status(List<UnitAdapter> data, String operation) {
    data.stream().forEach(unitAdapter -> unitAdapter.set_status(operation));

 入門小程序:

List<String> list = Arrays.asList("abc", "def", "1234");
        System.out.println("統計字符長度");
        System.out.println("方式一:lambda表達式");
        list.stream().map(e -> e.length()).forEach(e -> System.out.println(e));
        System.out.println("方式二:函數引用");
        list.stream().map(String :: length).forEach(System.out::println);
 
        System.out.println("mapToInt 將數據流中的元素結果轉換為 int 類型");
        list.stream().mapToInt(e -> e.length()).forEach(e -> System.out.println(e));
 
        System.out.println("mapToDouble 將數據流中的元素結果轉換為 Double 類型");
        list.stream().mapToDouble(e -> e.length()).forEach(e -> System.out.println(e));
 
 
        List<String> list2 = Arrays.asList("a-b-c-d","e-f-i-g-h");
        System.out.println("flatmap 作用就是將元素拍平拍扁");
        // flatmapToInt、flatmapToLong、flatmapToDouble 跟flatMap 都類似的,只是類型被限定了
        list2.stream().flatMap(e -> Stream.of(e.split("-"))).forEach(e -> System.out.println(e));
 
        System.out.println("limit 限制顯示元素的個數");
        List<Integer> list3 = Arrays.asList(1,2,3,4,5,6);
        list3.stream().limit(3).forEach(e -> System.out.println(e));
 
        System.out.println("distinct 去重");
        List<Integer> list4 = Arrays.asList(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1);
        list4.stream().distinct().forEach(e -> System.out.println(e));
 
        System.out.println("filter 過濾");
        list4.stream().filter(e -> e<3).forEach(e -> System.out.println(e));
 
        System.out.println("skip 跳過前幾個元素");
        List<String> list5 = Arrays.asList("a","b","c");
        list5.stream().skip(2).forEach(e -> System.out.println(e));
 
        System.out.println("sorted 排序,底層依賴Comparable 實現");
        list4.stream().sorted().forEach(e -> System.out.println(e));
 
        System.out.println("collect(Collectors.toSet()) 將元素收集到 Set 中");
        List<String> list6 = Arrays.asList("apple", "banana", "orange", "waltermaleon", "grape");
        list6.stream().collect(Collectors.toSet()).forEach(e -> System.out.println(e));
 
        System.out.println("count 統計數據流中的元素個數");
        System.out.println(list6.stream().count());
 
        System.out.println("findFirst 獲取第一個元素");
        System.out.println(list6.stream().findFirst());
 
        System.out.println("findAny 隨機獲取一個元素");
        System.out.println(list6.stream().parallel().findAny());
 
        System.out.println("noneMatch 集合中是否不存在指定字符,如果不存在返回 true,否則返回 false");
        System.out.println(list6.stream().noneMatch(e -> e.equals("orange")));
 
        System.out.println("anayMatch 集合中是否存在指定字符,如果存在返回 true,否則返回 false");
        System.out.println(list6.stream().anyMatch(e -> e.equals("orange")));
 
        System.out.println("min 查找最小的元素");
        List<Integer> list7 = Arrays.asList(1,2,3,4,5,6);
        System.out.println(list7.stream().min((e1, e2) -> e1.compareTo(e2)));
 
        System.out.println("max 查找最大的元素");
        System.out.println(list7.stream().max((e1, e2) -> e1.compareTo(e2)));
 
        System.out.println("reduce 是一個規約操作,所有的元素歸約成一個,比如對所有元素求和");
        System.out.println(list7.stream().reduce(0, (e1, e2) -> e1+e2));
 
        System.out.println("forEachOrdered 適用用於並行流的情況下進行迭代,能保證迭代的有序性");
        Stream.of(0,2,6,5,4,9,8,-1)
                .parallel()
                .forEach(e->{
                    System.out.println(Thread.currentThread().getName()+": "+e);});

 轉載自:https://www.cnblogs.com/tangshengwei/p/12587976.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM