亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java8中方便又實(shí)用的Map函數(shù)總結(jié)

 更新時(shí)間:2022年11月14日 10:50:43   作者:扣釘日記  
java8之后,常用的Map接口中添加了一些非常實(shí)用的函數(shù),可以大大簡(jiǎn)化一些特定場(chǎng)景的代碼編寫(xiě),提升代碼可讀性,快跟隨小編一起來(lái)看看吧

簡(jiǎn)介

java8之后,常用的Map接口中添加了一些非常實(shí)用的函數(shù),可以大大簡(jiǎn)化一些特定場(chǎng)景的代碼編寫(xiě),提升代碼可讀性,一起來(lái)看看吧。

computeIfAbsent函數(shù)

比如,很多時(shí)候我們需要對(duì)數(shù)據(jù)進(jìn)行分組,變成Map<Integer, List<?>>的形式,在java8之前,一般如下實(shí)現(xiàn):

List<Payment> payments = getPayments();
Map<Integer, List<Payment>> paymentByTypeMap = new HashMap<>();
for(Payment payment : payments){
    if(!paymentByTypeMap.containsKey(payment.getPayTypeId())){
        paymentByTypeMap.put(payment.getPayTypeId(), new ArrayList<>());
    }
    paymentByTypeMap.get(payment.getPayTypeId())
            .add(payment);
}

可以發(fā)現(xiàn)僅僅做一個(gè)分組操作,代碼卻需要考慮得比較細(xì)致,在Map中無(wú)相應(yīng)值時(shí)需要先塞一個(gè)空List進(jìn)去。

但如果使用java8提供的computeIfAbsent方法,代碼則會(huì)簡(jiǎn)化很多,如下:

List<Payment> payments = getPayments();
Map<Integer, List<Payment>> paymentByTypeMap = new HashMap<>();
for(Payment payment : payments){
    paymentByTypeMap.computeIfAbsent(payment.getPayTypeId(), k -> new ArrayList<>())
            .add(payment);
}

computeIfAbsent方法的邏輯是,如果map中沒(méi)有(Absent)相應(yīng)的key,則執(zhí)行l(wèi)ambda表達(dá)式生成一個(gè)默認(rèn)值并放入map中并返回,否則返回map中已有的值。

帶默認(rèn)值Map由于這種需要默認(rèn)值的Map太常用了,我一般會(huì)封裝一個(gè)工具類(lèi)出來(lái)使用,如下:

public class DefaultHashMap<K, V> extends HashMap<K, V> {
    Function<K, V> function;

    public DefaultHashMap(Supplier<V> supplier) {
        this.function = k -> supplier.get();
    }

    @Override
    @SuppressWarnings("unchecked")
    public V get(Object key) {
        return super.computeIfAbsent((K) key, this.function);
    }
}

然后再這么使用,如下:

List<Payment> payments = getPayments();
Map<Integer, List<Payment>> paymentByTypeMap = new DefaultHashMap<>(ArrayList::new);
for(Payment payment : payments){
    paymentByTypeMap.get(payment.getPayTypeId())
            .add(payment);
}

呵呵,這玩得有點(diǎn)像python的defaultdict(list)

臨時(shí)Cache有時(shí),在一個(gè)for循環(huán)中,需要一個(gè)臨時(shí)的Cache在循環(huán)中復(fù)用查詢(xún)結(jié)果,也可以使用computeIfAbcent,如下:

List<Payment> payments = getPayments();
Map<Integer, PayType> payTypeCacheMap = new HashMap<>();
for(Payment payment : payments){
    PayType payType = payTypeCacheMap.computeIfAbsent(payment.getPayTypeId(), 
            k -> payTypeMapper.queryByPayType(k));
    payment.setPayTypeName(payType.getPayTypeName());
}

因?yàn)閜ayments中不同payment的pay_type_id極有可能相同,使用此方法可以避免大量重復(fù)查詢(xún),但如果不用computeIfAbcent函數(shù),代碼就有點(diǎn)繁瑣晦澀了。

computeIfPresent函數(shù)

computeIfPresent函數(shù)與computeIfAbcent的邏輯是相反的,如果map中存在(Present)相應(yīng)的key,則對(duì)其value執(zhí)行l(wèi)ambda表達(dá)式生成一個(gè)新值并放入map中并返回,否則返回null。

這個(gè)函數(shù)一般用在兩個(gè)集合做等值關(guān)聯(lián)的時(shí)候,可少寫(xiě)一次判斷邏輯,如下:

@Data
public static class OrderPayment {
    private Order order;
    private List<Payment> payments;

    public OrderPayment(Order order) {
        this.order = order;
        this.payments = new ArrayList<>();
    }

    public OrderPayment addPayment(Payment payment){
        this.payments.add(payment);
        return this;
    }
}
public static void getOrderWithPayment(){
    List<Order> orders = getOrders();
    Map<Long, OrderPayment> orderPaymentMap = new HashMap<>();
    for(Order order : orders){
        orderPaymentMap.put(order.getOrderId(), new OrderPayment(order));
    }
    List<Payment> payments = getPayments();
    //將payment關(guān)聯(lián)到相關(guān)的order上
    for(Payment payment : payments){
        orderPaymentMap.computeIfPresent(payment.getOrderId(),
                (k, orderPayment) -> orderPayment.addPayment(payment));
    }
}

compute函數(shù)

compute函數(shù),其實(shí)和computeIfPresent、computeIfAbcent函數(shù)是類(lèi)似的,不過(guò)它不關(guān)心map中到底有沒(méi)有值,都執(zhí)行l(wèi)ambda表達(dá)式計(jì)算新值并放入map中并返回。

這個(gè)函數(shù)適合做分組迭代計(jì)算,像分組匯總金額的情況,就適合使用compute函數(shù),如下:

List<Payment> payments = getPayments();
Map<Integer, BigDecimal> amountByTypeMap = new HashMap<>();
for(Payment payment : payments){
    amountByTypeMap.compute(payment.getPayTypeId(), 
            (key, oldVal) -> oldVal == null ? payment.getAmount() : oldVal.add(payment.getAmount())
    );
}

當(dāng)oldValue是null,表示map中第一次計(jì)算相應(yīng)key的值,直接給amount就好,而后面再次累積計(jì)算時(shí),直接通過(guò)add函數(shù)匯總就好。

merge函數(shù)

可以發(fā)現(xiàn),上面在使用compute匯總金額時(shí),lambda表達(dá)式中需要判斷是否是第一次計(jì)算key值,稍微麻煩了點(diǎn),而使用merge函數(shù)的話(huà),可以進(jìn)一步簡(jiǎn)化代碼,如下:

List<Payment> payments = getPayments();
Map<Integer, BigDecimal> amountByTypeMap = new HashMap<>();
for(Payment payment : payments){
    amountByTypeMap.merge(payment.getPayTypeId(), payment.getAmount(), BigDecimal::add);
}

這個(gè)函數(shù)太簡(jiǎn)潔了,merge的第一個(gè)參數(shù)是key,第二個(gè)參數(shù)是value,第三個(gè)參數(shù)是值合并函數(shù)。

當(dāng)是第一次計(jì)算相應(yīng)key的值時(shí),直接放入value到map中,后面再次計(jì)算時(shí),使用值合并函數(shù)BigDecimal::add計(jì)算出新的匯總值,并放入map中即可。

putIfAbsent函數(shù)

putIfAbsent從命名上也能知道作用了,當(dāng)map中沒(méi)有相應(yīng)key時(shí)才put值到map中,主要用于如下場(chǎng)景:
如將list轉(zhuǎn)換為map時(shí),若list中有重復(fù)值時(shí),put與putIfAbsent的區(qū)別如下:

  • put保留最晚插入的數(shù)據(jù)。
  • putIfAbsent保留最早插入的數(shù)據(jù)。

forEach函數(shù)

說(shuō)實(shí)話(huà),java中要遍歷map,寫(xiě)法上是比較啰嗦的,不管是entrySet方式還是keySet方式,如下:

for(Map.Entry<String, BigDecimal> entry: amountByTypeMap.entrySet()){
    Integer payTypeId = entry.getKey();
    BigDecimal amount = entry.getValue();
    System.out.printf("payTypeId: %s, amount: %s \n", payTypeId, amount);
}

再看看在python或go中的寫(xiě)法,如下:

for payTypeId, amount in amountByTypeMap.items():
    print("payTypeId: %s, amount: %s \n" % (payTypeId, amount))

可以發(fā)現(xiàn),在python中的map遍歷寫(xiě)法要少寫(xiě)好幾行代碼呢,不過(guò),雖然java在語(yǔ)法層面上并未支持這種寫(xiě)法,但使用map的forEach函數(shù),也可以簡(jiǎn)化出類(lèi)似的效果來(lái),如下:

amountByTypeMap.forEach((payTypeId, amount) -> {
    System.out.printf("payTypeId: %s, amount: %s \n", payTypeId, amount);
});

總結(jié)

一直以來(lái),java因代碼編寫(xiě)太繁瑣而被開(kāi)發(fā)者們所廣泛詬病,但從java8開(kāi)始,從Map、Stream、var、multiline-string再到record,java在代碼編寫(xiě)層面做了大量的簡(jiǎn)化,java似乎開(kāi)竅了

到此這篇關(guān)于Java8中方便又實(shí)用的Map函數(shù)總結(jié)的文章就介紹到這了,更多相關(guān)Java8 Map函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java發(fā)起http請(qǐng)求的完整步驟記錄

    Java發(fā)起http請(qǐng)求的完整步驟記錄

    這篇文章主要給大家介紹了關(guān)于Java發(fā)起http請(qǐng)求的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Java實(shí)現(xiàn)房屋出租系統(tǒng)詳解

    Java實(shí)現(xiàn)房屋出租系統(tǒng)詳解

    這篇文章主要介紹了實(shí)現(xiàn)Java房屋出租系統(tǒng)的實(shí)現(xiàn)過(guò)程,文章條理清晰,在實(shí)現(xiàn)過(guò)程中加深了對(duì)相關(guān)概念的理解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • 詳解springboot設(shè)置cors跨域請(qǐng)求的兩種方式

    詳解springboot設(shè)置cors跨域請(qǐng)求的兩種方式

    這篇文章主要介紹了詳解springboot設(shè)置cors跨域請(qǐng)求的兩種方式,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-11-11
  • IntelliJ?IDEA快速查詢(xún)maven依賴(lài)關(guān)系圖文教程

    IntelliJ?IDEA快速查詢(xún)maven依賴(lài)關(guān)系圖文教程

    Maven提供了來(lái)查看依賴(lài)關(guān)系,而IDE往往提供了更加便利的方式,比如Eclipse或者IDEA都有類(lèi)似的功能,下面這篇文章主要給大家介紹了關(guān)于IntelliJ?IDEA快速查詢(xún)maven依賴(lài)關(guān)系的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • java實(shí)現(xiàn)本地緩存的示例代碼

    java實(shí)現(xiàn)本地緩存的示例代碼

    在高性能服務(wù)架構(gòu)設(shè)計(jì)中,緩存是不可或缺的環(huán)節(jié),因此這篇文章主要為大家詳細(xì)介紹了java中如何實(shí)現(xiàn)本地緩存,感興趣的小伙伴可以了解一下
    2024-01-01
  • java實(shí)現(xiàn)上傳文件到服務(wù)器和客戶(hù)端

    java實(shí)現(xiàn)上傳文件到服務(wù)器和客戶(hù)端

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)上傳文件到服務(wù)器和客戶(hù)端,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • Tomcat和Spring中的事件機(jī)制深入講解

    Tomcat和Spring中的事件機(jī)制深入講解

    這篇文章主要給大家介紹了關(guān)于Tomcat和Spring中事件機(jī)制的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧
    2018-12-12
  • Spring的自動(dòng)裝配常用注解詳解

    Spring的自動(dòng)裝配常用注解詳解

    這篇文章主要介紹了Spring的自動(dòng)裝配常用注解詳解,自動(dòng)裝配就是指 Spring 容器在不使用 <constructor-arg> 和<property> 標(biāo)簽的情況下,可以自動(dòng)裝配相互協(xié)作的 Bean 之間的關(guān)聯(lián)關(guān)系,將一個(gè) Bean 注入其他 Bean 的 Property 中,需要的朋友可以參考下
    2023-08-08
  • 詳解Java類(lèi)加載器與雙親委派機(jī)制

    詳解Java類(lèi)加載器與雙親委派機(jī)制

    這篇文章主要為大家介紹一下Java中的類(lèi)加載器與雙親委派機(jī)制,文中通過(guò)示例為大家進(jìn)行了詳細(xì)的介紹,對(duì)我們學(xué)習(xí)Java有一定幫助,需要的可以參考一下
    2022-08-08
  • springboot2.0整合logback日志的詳細(xì)代碼

    springboot2.0整合logback日志的詳細(xì)代碼

    這篇文章主要介紹了springboot2.0整合logback日志的應(yīng)用場(chǎng)景分析,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02

最新評(píng)論