最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

簡介

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

computeIfAbsent函數(shù)

比如,很多時候我們需要對數(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)僅僅做一個分組操作,代碼卻需要考慮得比較細(xì)致,在Map中無相應(yīng)值時需要先塞一個空List進(jìn)去。

但如果使用java8提供的computeIfAbsent方法,代碼則會簡化很多,如下:

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中沒有(Absent)相應(yīng)的key,則執(zhí)行l(wèi)ambda表達(dá)式生成一個默認(rèn)值并放入map中并返回,否則返回map中已有的值。

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

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)

臨時Cache有時,在一個for循環(huán)中,需要一個臨時的Cache在循環(huán)中復(fù)用查詢結(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ù)查詢,但如果不用computeIfAbcent函數(shù),代碼就有點(diǎn)繁瑣晦澀了。

computeIfPresent函數(shù)

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

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

@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ù)是類似的,不過它不關(guān)心map中到底有沒有值,都執(zhí)行l(wèi)ambda表達(dá)式計(jì)算新值并放入map中并返回。

這個函數(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ì)算時,直接通過add函數(shù)匯總就好。

merge函數(shù)

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

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

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

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

putIfAbsent函數(shù)

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

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

forEach函數(shù)

說實(shí)話,java中要遍歷map,寫法上是比較啰嗦的,不管是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中的寫法,如下:

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

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

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

總結(jié)

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

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

相關(guān)文章

  • Mybatis-plus?sql注入及防止sql注入詳解

    Mybatis-plus?sql注入及防止sql注入詳解

    mybatis-plus提供了許多默認(rèn)單表 CRUD 語句,對于其他SQL情況愛莫能助,下面這篇文章主要給大家介紹了關(guān)于Mybatis-plus?sql注入及防止sql注入的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • MybatisPlus lambdaQueryWrapper中常用方法的使用

    MybatisPlus lambdaQueryWrapper中常用方法的使用

    本文主要介紹了MybatisPlus lambdaQueryWrapper中常用方法的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Java21增強(qiáng)對Emoji表情符號處理示例詳解

    Java21增強(qiáng)對Emoji表情符號處理示例詳解

    這篇文章主要為大家介紹了Java21增強(qiáng)對Emoji表情符號處理示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • 詳解Java設(shè)計(jì)模式之抽象工廠模式

    詳解Java設(shè)計(jì)模式之抽象工廠模式

    設(shè)計(jì)模式是軟件設(shè)計(jì)中的一種常見方法,通過定義一系列通用的解決方案,來解決常見的軟件設(shè)計(jì)問題,其中,抽象工廠模式是一種非常常見的設(shè)計(jì)模式,文中有詳細(xì)的代碼示例供大家參考,感興趣的同學(xué)可以借鑒閱讀
    2023-05-05
  • springboot啟動時候報(bào)錯mongodb問題

    springboot啟動時候報(bào)錯mongodb問題

    這篇文章主要介紹了springboot啟動時候報(bào)錯mongodb問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • spring boot 3.3.0和mybatis plus 3.5.6版本沖突的問題解決

    spring boot 3.3.0和mybatis plus 3.5.6版本沖突

    這篇文章主要介紹了spring boot 3.3.0和mybatis plus 3.5.6版本沖突的問題解決,文中介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07
  • 配置DispatcherServlet的方法介紹

    配置DispatcherServlet的方法介紹

    今天小編就為大家分享一篇關(guān)于配置DispatcherServlet的方法介紹,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • SpringCloud中Gateway的使用教程詳解

    SpringCloud中Gateway的使用教程詳解

    SpringCloud?Gateway是Spring體系內(nèi)的一個全新項(xiàng)目,它旨在為微服務(wù)架構(gòu)提供一種簡單有效的統(tǒng)一的API路由管理方式。本文就來為大家詳細(xì)講講Gateway的使用教程,需要的可以參考一下
    2022-08-08
  • SpringBoot整合RabbitMQ實(shí)現(xiàn)流量消峰

    SpringBoot整合RabbitMQ實(shí)現(xiàn)流量消峰

    RabbitMQ 即一個消息隊(duì)列,主要是用來實(shí)現(xiàn)應(yīng)用程序的異步和解耦,同時也能起到消息緩沖,消息分發(fā)的作用,消息中間件在互聯(lián)網(wǎng)公司的使用中越來越多,本文給大家介紹了SpringBoot整合RabbitMQ實(shí)現(xiàn)流量消峰,需要的朋友可以參考下
    2024-12-12
  • java 算法之希爾排序詳解及實(shí)現(xiàn)代碼

    java 算法之希爾排序詳解及實(shí)現(xiàn)代碼

    這篇文章主要介紹了java 算法之希爾排序詳解及實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下
    2017-03-03

最新評論

黑水县| 静乐县| 益阳市| 酉阳| 浙江省| 平潭县| 汝州市| 长顺县| 大厂| 和林格尔县| 泰州市| 佛教| 红原县| 颍上县| 海林市| 辛集市| 美姑县| 萍乡市| 论坛| 仁布县| 荣昌县| 凉城县| 宜城市| 玉龙| 红原县| 旬邑县| 当涂县| 且末县| 张家港市| 定日县| 军事| 齐齐哈尔市| 玛曲县| 仙居县| 恩平市| 平乐县| 屯昌县| 沐川县| 南木林县| 贺兰县| 怀柔区|