-Java forEach中 Lambda Expr中的 final變量要求

本文是關於 -Java Lambda Expression在forEach方法的應用討論。對比其餘編程語言的foreach 操做(文末附帶7種主要編程語言的Loop HashMap by forEach的程序片斷),Java 8引入的運用 Lambda Expression方式的 forEach操做方法是最接近語言所要表達的本意,且簡潔、直接。
在持續優化 -GWA2 in -Java 過程當中,因爲 -GWA2 多層結構設計,層間數據傳遞不少依賴Map/HashMap完成,常常用到這個 forEach 並碰到一些問題(引入外部變量,有條件篩選及終止等),茲記錄相關探索過程以下。html

一般在 -Java 中遍歷一個數據集合是常見的操做場景,好比遍歷數組 (-R/G2ST ):java

int[] numbers = 
             {1,2,3,4,5,6,7,8,9,10};
for (int item : numbers) {
    System.out.println("Count is: " + item);
}

再好比常規的藉助 keySet遍歷一個key-value結構的 Map / Hash, 哈希 (-R/k2SP ):web

for (KeyType key : m.keySet()){
    System.out.println(key+", "+m.get(key));
}

-R/k2SP 列舉了三種方法進行遍歷key-value 的Map, 實際上根據 -R/92SS  頁面上第二個回答所進行的測試,大概有十多種方法能夠實現遍歷一個 key-value 的Map. 這麼多方法中,又以 forEach 的表達最爲直接、高效,因此推薦使用 Map.forEach .編程

forEach 本質上是建造一個 Lambda Expression 並進行運算,其中 Map.forEach 等同的表達式也是針對  keySet的調用( -R/V2SQ )。api

//- Map.forEach is equivalent to:
for (Map.Entry<K, V> entry : map.entrySet())
     action.accept(entry.getKey(), entry.getValue());

//- an example
HashMap<String, Integer> hm = new HashMap<String, Integer>();
hm.forEach((key, val)->{
    System.out.println(key+」, 「+val);
    });數組

因爲 Lambda Expression 是一個 enclosing scope,它與代碼區塊外的溝通成爲問題,外部變量沒法在 Lambda 內部調用,內部變量也沒法在外部訪問到。在這近乎隔離的運行時環境裏,還留了final變量能夠穿行的縫隙,若是要實現將Lambda Expr與外部變量進行數據交換,就須要在代碼區塊外部定義final類型變量做爲數據信息載體。常見的應用有以下兩個場景.服務器

  1. 將Map/HashMap的數據遍歷並加工
    例子程序:
    HashMap<String, Integer> hm = new HashMap<String, Integer>();
    final HashMap<String, Integer> hm2 = new HashMap<String, Integer>();
    hm.forEach((key, val)->{
        System.out.println(key+」, 「+val);
        hm2.put(key, val + 1);
        });

    藉助 Lambda Expression 對 final變量的支持,能夠容易地將遍歷並加工後的數據中轉取出作進一步的操做. 
    final 變量因爲沒法再次出如今賦值語句的左邊,也即沒法對對象作再次賦值操做。但這不影響咱們後續將 hm2的值進行遍歷或者將其複製到另一個非final的對象中去,如上例中的 hm.
    一樣地,做爲final的 hm2 沒法總體被賦值,但能夠對其自己進行操做,如上例中的,經過 hm2.put 將某個元素放入這個容器中。相似的還有,好比 StringBuffer 的操做。網絡

    StringBuffer pageIdsb = new StringBuffer(「0」);
    pageList.forEach((k, v)->{
        HashMap tmphm = (HashMap)v;
        pageIdsb.append(「,」).append(tmphm.get(「id」));
        });
    public final class StringBuffer
    extends Object
    implements Serializable, CharSequence

    由 StringBuffer 類的定義(-R/V2SQ ),咱們知道其是 final 類,因而在初始化後,能夠在 Lambda Expr中經過 pageIdsb.append 的方式進行其值的操做與變化。架構

     

  2. 有條件過濾或推出、終止遍歷
    在遍歷Map/HashMap等對象集合時,有時候須要有條件的過濾或者終止,若是將外部約束條件帶入? 
    又如何定義內部自循環變量?
    一種可行的方式,依然是使用 final變量,而後基本變量類型,若是定義爲final以後則不能被直接修改,沒法知足循環體內計數的需求.
    因而就須要設計一個複合final類的變量,其成員一個負責約束條件,另一個負責循環計數。
    HashMap<String, Integer> hm = new HashMap<String, Integer>();
    final HashMap<String, Integer> hm2 = new HashMap<String, Integer>(){{
        put(「iCount」, 0);
        put(「maxCount」, 4);
        }};
    hm.forEach((key, val)->{
        int iCount = Wht.parseInt(hm2.get(「iCount」));
        int maxCount = Wht.parseInt(hm2.get(「maxCount」));
        if(iCount < maxCount){
            System.out.println(key+」, 「+val);
        }
        hm2.put(「iCount」, iCount + 1);
        });

    在上面的例子程序中,咱們定義了循環體內計數變量 iCount 和 知足退出條件 maxCount 每次循環時取出並作對比,每次循環時, iCount++ 。
    上面例子程序中的 Wht.parseInt 是 -GWA2 的基礎設施類,能夠在 -GWA2@Github-R/h2SO )下載到.
    上面例子程序中的hm2 的聲明實例中,經過構造方法並以一個匿名類完成了兩個 put操做。關於匿名類 Anonymous Class,參考 -Java 文檔(-R/i2SP ), 在 -GWA2 in -Java 裏也有很多應用。oracle

-Java 中引入的 forEach 操做,儘管是以 Lambda Expression爲載體的一個 Consumer / BiConsumer對象,運行在一個 enclosing scope,依靠能夠外部 final 變量這個渠道,能夠提供媲美其餘編程語言同樣的 foreach 效果,對增長程序可讀性、可維護性有必定的幫助,已有的評測 forEach也表現出不錯的性能,值得更多地應用。

-GWA2 是」通用網絡應用架構( General Web Application Architeture )」,基於 -GWA2 能夠輕便構建各類網絡應用程序,
包括複雜的在線購物商城、 旅遊交易平臺、社羣或者社交網站和新聞資訊網站等,
也包括各類企事業單位網上門戶,在線交互及服務做業系統等.
還能夠包括爲NativeApp作服務器端支持, 甚至是WebApp的所有.
-GWA2 是爲數很少的支持跨開發語言的應用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .

-GWA2 is a 「General Web Application Architecture」 and based on -GWA2 developers can easily build a variety of network applications,
including complex online shopping malls, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various online portals of enterprises and institutions, online interaction and service operations systems.
Moreover it contains server-side support for NativeApp, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.

-GWA2 is E.A.S.Y 
Easy Along, Swift Yield
輕鬆啓動, 快速產出.

----

(1) Loop HashMap in PHP ****

$hm = array(「a」=>1, 「b」=>2, 「c」=>3);
foreach($hm as $key=>$val){
    print 「key:$key , val:$val\n」;
}

(2) Loop HashMap in Perl ***

my %hm = (「a」=>1, 「b」=>2, 「c」=>3);
foreach my $key (keys %hm){
    my $val = $hm{$key};
    print 「key:$key , val:$val\n」;
}

(3) Loop HashMap in Swift *****

let hm = [「a」:1, 「b」:2, 「c」:3];
for (key, val) in hm {
    print(「key:\(key) , val:\(val)\n」);
}

(4) Loop HashMap in Python ***

hm = {「a」:1, 「b」:2, 「c」:3};
for key in hm:
    print(「key:{} , val:{}」.format(key, hm[key]));

(5) Loop HashMap in C++ *

std::map<std::string, std::int> hm {
    {「a」, 1},
    {「b」, 1},
    {「c」, 3}
};
for(const auto& key : hm){
    std::cout << 「key:」 << key.first
        << 」 , val:」 << key.second
        << 「\n」;
}

(6) Loop HashMap in JavaScript ***

var hm = {「a」:1, 「b」:2, 「c」:3};
for (var key in hm){
    console.log(「key:」+key+」 , val:」+hm[key]);
};

(7) Loop HashMap in Java ***

HashMap<String, Integer> hm = new HashMap<String, Integer>(){{
    put(「a」, 1″);
    put(「b」, 2);
    put(「c」, 3);
}};
hm.forEach((key, val)->{
    System.out.println(key+」, 「+val);
    });

 ----

-R/G2SU 

相關文章
相關標籤/搜索