Java lambda表達式實踐系列——如何優(yōu)雅地刪除列表元素糠赦?

推薦閱讀:Java8 lambda表達式10個示例

在編程實踐中,經(jīng)常會遇到這樣的需求場景:遍歷一個列表磅废,把其中不滿足某些條件的元素刪掉纳像。

下面我們寫幾個方法來嘗試用不同的方式來實現(xiàn)這個需求:

先準備兩個校驗方法

    /**
     * 校驗一個字符串是否合法的方法,字符串的長度大于等于6才是合法的
     * 
     * @param str
     * @return
     */
    public static boolean isValid(String str) {
        if (null == str || str.length() < 6) {
            return false;
        }
        return true;
    }

    public static boolean isNotValid(String str) {
        return !isValid(str);
    }

方式1:在for-each循環(huán)中刪除列表元素

    public static void method1() {
        List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("abc");
        list.add(null);
        list.add("123456");
        list.add("");

        for (String str : list) {
            if (isNotValid(str)) {
                list.remove(str);
            }
        }
        System.out.println(list);
        System.out.println(list.hashCode());
    }

運行上面這個方法拯勉,報異常:

java.util.ConcurrentModificationException

可見竟趾,并不能在for-each循環(huán)遍歷一個列表時去刪除這個列表的元素,此種方法行不通宫峦。

方式2:使用迭代器刪除列表元素

    public static void method2() {
        List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("abc");
        list.add(null);
        list.add("123456");
        list.add("");
        System.out.println(list);
        System.out.println(list.hashCode());

        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            String str = it.next();
            if (isNotValid(str)) {
                it.remove();
            }
        }
        System.out.println(list);
        System.out.println(list.hashCode());
    }

運行這個方法岔帽,輸出:

[1, abc, null, 123456, ] 
667562667 
[123456] 
1450575490

可見使用迭代器可以在遍歷列表的同時正常地刪除列表的元素,并且刪除元素之后列表的內(nèi)存地址已經(jīng)發(fā)生了變化导绷。

方式3:使用lambda表達式刪除列表元素

上面使用迭代器的方式雖然能夠正常地刪除列表中的元素犀勒,但還是不夠優(yōu)雅,因為要寫好幾行的遍歷代碼妥曲,顯得略臃腫账蓉。能不能只用一行代碼完成這個功能呢?答案是可以的——使用lambda表達式:

    public static void method3() {
        List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("abc");
        list.add(null);
        list.add("123456");
        list.add("");
        System.out.println(list);
        System.out.println(list.hashCode());

        list.removeIf(e -> isNotValid(e));
        System.out.println(list);
        System.out.println(list.hashCode());
    }

運行上面的方法逾一,輸出:

[1, abc, null, 123456, ] 
667562667 
[123456] 
1450575490

可見使用lambda表達式的方法更為優(yōu)雅铸本,這里使用了List接口所繼承的Collection接口在JDK 1.8新增的removeIf方法,該方法接收一個Predicate類型的參數(shù)遵堵,刪除列表中滿足Predicate條件的元素箱玷。在這里使用lambda表達式:e -> isNotValid(e)定義了這樣一個Predicate函數(shù)怨规。

方式4:使用方法引用刪除列表元素

除了lambda表達式,JDK 1.8還可以用一種稱為方法引用的方式來刪除列表中的元素锡足,使用類似C++的::運算符波丰,來引用一個對象的實例方法或一個類的類方法,下面就用方法引用的方式來刪除一個列表中的指定元素:

    public static void method4() {
        List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("abc");
        list.add(null);
        list.add("123456");
        list.add("");
        System.out.println(list);
        System.out.println(list.hashCode());

        list.removeIf(RemoveListElement::isNotValid);  // isNotValid為RemoveListElement類的一個靜態(tài)方法
        System.out.println(list);
        System.out.println(list.hashCode());
    }

運行上面的方法舶得,輸出:

[1, abc, null, 123456, ] 
667562667 
[123456] 
1450575490

可見使用方法引用的方式也可以達到同樣的目的掰烟,但無疑比lambda表達式更為簡潔、優(yōu)雅沐批。

總結(jié)

經(jīng)過上述對比纫骑,可以看出:

  • 在JDK 1.8之前,要使用迭代器的方式才能在遍歷一個列表的時候正確地刪除列表中的元素九孩。
  • 在JDK 1.8及之后先馆,還可以使用lambda表達式和方法引用的方式正確地刪除列表中的元素,這兩種方式更為優(yōu)雅躺彬。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末煤墙,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子宪拥,更是在濱河造成了極大的恐慌仿野,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件她君,死亡現(xiàn)場離奇詭異脚作,居然都是意外死亡,警方通過查閱死者的電腦和手機犁河,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門鳖枕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人桨螺,你說我怎么就攤上這事宾符。” “怎么了灭翔?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵魏烫,是天一觀的道長。 經(jīng)常有香客問我肝箱,道長哄褒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任煌张,我火速辦了婚禮呐赡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘骏融。我一直安慰自己链嘀,他們只是感情好萌狂,可當我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著怀泊,像睡著了一般茫藏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上霹琼,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天务傲,我揣著相機與錄音,去河邊找鬼枣申。 笑死售葡,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的糯而。 我是一名探鬼主播天通,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼泊窘,長吁一口氣:“原來是場噩夢啊……” “哼熄驼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起烘豹,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤瓜贾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后携悯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祭芦,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年憔鬼,在試婚紗的時候發(fā)現(xiàn)自己被綠了龟劲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡轴或,死狀恐怖昌跌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情照雁,我是刑警寧澤蚕愤,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站饺蚊,受9級特大地震影響萍诱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜污呼,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一裕坊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧燕酷,春花似錦籍凝、人聲如沸映企。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽堰氓。三九已至,卻和暖如春苹享,著一層夾襖步出監(jiān)牢的瞬間双絮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工得问, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留囤攀,地道東北人。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓宫纬,卻偏偏與公主長得像焚挠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子漓骚,可洞房花燭夜當晚...
    茶點故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容