小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

別再這么寫代碼了,這幾個(gè)方法不香嗎?

 行者花雕 2021-04-28

JDK8 應(yīng)該是 Java 中最堅(jiān)挺一個(gè)版本,這個(gè)版本新增很多特性,讓我們開(kāi)發(fā)起來(lái)多了很多便利。

不過(guò)最近 Review 項(xiàng)目代碼的時(shí)候發(fā)現(xiàn),雖然很多項(xiàng)目工程已經(jīng)使用了 JDK8,但是工程代碼卻很少使用到 JDK8 新特性、新方法。

如果單從代碼正確性上來(lái)說(shuō),老方式寫法寫當(dāng)然沒(méi)有什么問(wèn)題,那唯一的缺點(diǎn)其實(shí)就是代碼行數(shù)比較多,比較繁瑣。

那同樣的需求,使用 JDK8 新方法,其實(shí)幾行代碼就可以搞定,這樣代碼就會(huì)變得非常簡(jiǎn)潔。

今天就以三個(gè)比較常見(jiàn)的場(chǎng)景為例,教你幾招,使用 JDK8 Map新增的方法簡(jiǎn)化代碼開(kāi)發(fā)。

下面就來(lái)看看這次即將用到 Map幾個(gè)新方法:

歡迎關(guān)注我的公眾號(hào):小黑十一點(diǎn)半,獲得日常干貨推送。如果您對(duì)我的專題內(nèi)容感興趣,也可以關(guān)注我的博客:

預(yù)防空指針問(wèn)題

日常開(kāi)發(fā)中我們通常會(huì)從 Map獲取元素,然后進(jìn)行相關(guān)的業(yè)務(wù)處理,示例代碼如下:

Map<String, String> map = new HashMap();
map.put("公號(hào)", "小黑十一點(diǎn)半");
map.put("主理人", "樓下小黑哥");
// 可能存在 NPE 問(wèn)題
System.out.println(map.get("支付").toUpperCase());

如果就像示例代碼直接處理,一旦 Map中相應(yīng)元素不存在,那么我們就會(huì)碰到空指針問(wèn)題。

為了解決這個(gè)問(wèn)題,通常我們可以先判斷一下元素是否為 null,如果不為 null,再做相應(yīng)的業(yè)務(wù)處理。

// 第一種 if 判空
String value = map.get("支付");
if (!Objects.isNull(value)) {
    System.out.println(value.toUpperCase());
}

這種方式唯一劣勢(shì)就是代碼處理上比較繁瑣,不是很簡(jiǎn)潔。

所以針對(duì)這種情況,其實(shí)可以使用條件運(yùn)算符,設(shè)置一個(gè)默認(rèn)空值,從而避免后續(xù)處理發(fā)生空指針。

// 第一種 if 判空
String value = map.get("支付");
// 第二種 條件運(yùn)算符
value = Objects.isNull(value) ? "" : value;

這種方式比較簡(jiǎn)潔,所以日常開(kāi)發(fā)中我比較喜歡用這種方式。

ps: 這里的前提,空字符串對(duì)于業(yè)務(wù)沒(méi)有特殊意義。如果存在特殊意義,那就不能使用這種方式了。

那如果使用 JDK8 ,其實(shí)就很方便了,我們就可以使用 Map#getOrDefault直接代替條件運(yùn)算符。

// 等同于條件運(yùn)算符的效果: Objects.isNull(value) ? "" : value;
String value = map.getOrDefault("支付","");

借助 Map#getOrDefault 一行代碼直接搞定,就是這么簡(jiǎn)單。

如果你還在使用 JDK8 之前的版本,沒(méi)辦法使用這個(gè)方法。沒(méi)關(guān)系,我們可以借助 Apache Common-Lang3 提供的工具類 MapUtils 避免空指針。

// Apache MapUtils
String value = MapUtils.getString(map, "支付", "");

MapUtils這個(gè)工具類相對(duì)于Map#getOrDefault有一個(gè)好處,針對(duì)傳入 Mapnull 的情況,可以設(shè)置默認(rèn)值。

假設(shè)我們是從 POJO對(duì)象獲取 Map 參數(shù),這個(gè)時(shí)候?yàn)榱朔乐箍罩羔?,我們就需要提前做一個(gè)空指針的判斷。

不過(guò)如果使用 MapUtils,那我們就不需要判斷是否為 null,方法內(nèi)部已經(jīng)封裝這個(gè)邏輯。

MapUtils.getString(pojo.getMap(),"支付", "");

巧用 computeIfAbsent

日常開(kāi)發(fā)中,我們會(huì)碰到這類場(chǎng)景,需要一個(gè)鍵需要映射到多個(gè)值,這個(gè)時(shí)候我們可以使用 Map<K, List<V>>這個(gè)結(jié)構(gòu)。

此時(shí)添加元素的時(shí)候,我們需要做一些判斷,當(dāng)內(nèi)部元素不存在時(shí)候主動(dòng)創(chuàng)建一個(gè)集合對(duì)象,示例代碼如下:

Map<String, List<String>> map = new HashMap();

List<String> classify = map.get("java框架");
if (Objects.isNull(classify)) {
    classify = new ArrayList<>();
    classify.add("Spring");
    map.put("java框架", classify);
} else {
    classify.add("Spring");
}

上面的代碼比較繁瑣,到了 JDK8,Map新增一個(gè) computeIfAbsent方法:

default V computeIfAbsent(K key,
        Function<? super K, ? extends V> mappingFunction) {

如果 Mapkey 對(duì)應(yīng)的 value 不存在,則會(huì)將 mappingFunction 計(jì)算產(chǎn)生的值作為保存為該 keyvalue,并且返回該值。否則不作任何計(jì)算,將會(huì)直接返回 key 對(duì)應(yīng)的 value。

利用這個(gè)特性,我們可以直接使用 Map#computeIfAbsent一行代碼完成上面的場(chǎng)景,示例代碼如下:

map.computeIfAbsent("java框架", key -> new ArrayList<>()).add("Spring");

那其實(shí) Map 中還有一個(gè)方法 putIfAbsent,功能跟 computeIfAbsent比較類似。

那剛開(kāi)始使用的時(shí)候,誤以為可以使用 putIfAbsent完成上面的需求:

// ERROR:會(huì)有 NPE 問(wèn)題
map.putIfAbsent("java框架", new ArrayList<>()).add("Spring");

那其實(shí)這是錯(cuò)誤的,當(dāng) Mapkey 對(duì)應(yīng) value 不存在的時(shí)候,putIfAbsent將會(huì)直接返回 null。

computeIfAbsent將會(huì)返回 mappingFunction計(jì)算之后的值,像上面的場(chǎng)景直接返回就是 new ArrayList。

這一點(diǎn)需要注意一下,切勿用錯(cuò)方法,導(dǎo)致空指針。

最后針對(duì)上面這種一個(gè)鍵需要映射到多個(gè)值,其實(shí)還有一個(gè)更優(yōu)秀的解決辦法,使用 Google Guava 提供的新集合類型 Multiset,以此快速完成一個(gè)鍵需要映射到多個(gè)值的場(chǎng)景。

示例代碼如下:

ArrayListMultimap<Object, Object> multiset= ArrayListMultimap.create();
multiset.put("java框架","Spring");
multiset.put("java框架","Mybatis");
// java框架--->Spring,Mybatis

單詞統(tǒng)計(jì)

假設(shè)有如下需求,我們需要統(tǒng)計(jì)一段文字中相關(guān)單詞出現(xiàn)的次數(shù)。那實(shí)現(xiàn)方式其實(shí)很簡(jiǎn)單,使用 Map存儲(chǔ)相關(guān)單詞的次數(shù)即可,示例代碼如下:

Map<String, Integer> countMap = new HashMap();
Integer count = countMap.get("java");
if (Objects.isNull(count)) {
    countMap.put("java", 1);
} else {
    countMap.put("java", count++);
}

這類代碼是不是很熟悉?同樣比較繁瑣。

接下來(lái)我們可以使用 JDK8 Map 新增方法進(jìn)行改造,這次使用上面用過(guò)的 getOrDefault 再加 put 方法快速解決,示例代碼如下:

// getOrDefault
Integer count = countMap.getOrDefault("java",0);
countMap.put("java", count + 1);

那其實(shí)我們還有一種辦法,這次我們使用 Map#merge這個(gè)新方法,一句代碼完成上述需求,示例代碼如下:

countMap.merge("java", 1, Integer::sum);

說(shuō)真的,剛看到 merge這個(gè)方法的時(shí)候還是有點(diǎn)懵,尤其后面直接使用 lambda 函數(shù),讓人不是很好理解。

這里先將lambda 函數(shù)還原成正常類,給大家著重解釋一下這個(gè)方法:

countMap.merge("java", 1, new BiFunction<Integer, Integer, Integer>() {
    @Override
    public Integer apply(Integer oldValue, Integer newValue) {
        return Integer.sum(oldValue,newValue);
    }
});

用上面代碼說(shuō)明一下merge方法,如果 java這個(gè)值在 countMap中不存在,那么將會(huì)其對(duì)應(yīng)的 value 設(shè)置為 1。

那如果 javacountMap 中存在,則會(huì)調(diào)用第三個(gè)參數(shù) remappingFunction 函數(shù)方法進(jìn)行計(jì)算。

remappingFunction 函數(shù)中,oldValue代表原先 countMapjava 的值,newValue代表我們?cè)O(shè)置第二個(gè)參數(shù) 1,這里我們將兩者相加,剛好完成累加的需求。

最后

這次主要從個(gè)人日常碰到三個(gè)場(chǎng)景出發(fā),給大家對(duì)比了一下使用 JDK8 Map 新增方法只會(huì),兩者代碼區(qū)別。

從上面可以很明顯看出,使用新增方法之后,我們可以用很少的代碼可以完成,整體看起來(lái)變得非常簡(jiǎn)潔。

不過(guò) JDK8 之后很多方法都會(huì)用到 lambda 函數(shù),不熟悉的話,其實(shí)比較難以理解代碼。

不過(guò)也還好,我們只要在日常編碼過(guò)程中,刻意去練習(xí)使用,很快就能上手。

最后,JDK8 還有許多好用方法,刻意簡(jiǎn)化代碼開(kāi)發(fā),你可以在留言區(qū)推薦幾個(gè)嗎?

歡迎關(guān)注我的公眾號(hào):小黑十一點(diǎn)半,獲得日常干貨推送。如果您對(duì)我的專題內(nèi)容感興趣,也可以關(guān)注我的博客:

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多