自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Map 只會(huì) put、get?快來(lái)學(xué)這幾個(gè)“新”方法

開(kāi)發(fā) 前端
目前JDK的最新LTS版本已經(jīng)更新到21了,這幾個(gè)在JDK8引入的Map”新“方法其實(shí)也是”老“方法了,還沒(méi)熟練使用也太out了,快來(lái)看看你都”學(xué)廢“了嗎?

引子

Map的數(shù)據(jù)操作,你是不是還只會(huì)put、get?

Map是我們?nèi)粘>幊讨惺殖S玫臄?shù)據(jù)接口,的在JDK8中,Map引入了幾個(gè)新方法,可以簡(jiǎn)化我們對(duì)Map中數(shù)據(jù)的操作。

目前JDK的最新LTS版本已經(jīng)更新到21了,這幾個(gè)在JDK8引入的Map”新“方法其實(shí)也是”老“方法了,還沒(méi)熟練使用也太out了,快來(lái)看看你都”學(xué)廢“了嗎?

getOrDefault

這個(gè)方法名很直觀(guān),見(jiàn)名知意:嘗試獲取key對(duì)應(yīng)的值,如果未獲取到,就返回默認(rèn)值。

看一個(gè)使用的例子,新寫(xiě)法會(huì)比老寫(xiě)法更加簡(jiǎn)潔:

private static void testGetOrDefault() {
    Map<String, String> map = new HashMap<>(4);
    map.put('123', '123');
    String key = 'key';
    String defaultValue = 'defaultValue';

    // 老寫(xiě)法
    String oldValue = defaultValue;
    if (map.containsKey(key)) {
        oldValue = map.get(key);
    }
    System.out.println('oldValue = ' + oldValue);

    // 新寫(xiě)法
    String newValue = map.getOrDefault(key, defaultValue);
    System.out.println('newValue = ' + newValue);
}

foreach

看方法名也可以知道,這個(gè)方法是遍歷map的數(shù)據(jù)使用的。

如果沒(méi)有foreach,我們遍歷map的時(shí)候一般是使用增強(qiáng)for循環(huán),有了這個(gè)方法后,可以更加方便使用entry中的key和val:

private static void testForeach() {
    Map<String, String> map = new HashMap<>(4);
    map.put('123', '123');

    // 老寫(xiě)法
    for (Map.Entry<String, String> entry : map.entrySet()) {
        System.out.printf('老寫(xiě)法 key = %s, value = %s%n', entry.getKey(), entry.getValue());
    }

    // 新寫(xiě)法
    map.forEach((key, value) -> System.out.printf('新寫(xiě)法 key = %s, value = %s%n', key, value));
}

merge

從名字可以想到,是合并entry使用的,但是具體是怎么合并呢?

看一下日常最常用的Map實(shí)現(xiàn)類(lèi)HashMap對(duì)merge方法的實(shí)現(xiàn)

@Override
public V merge(K key, V value,
               BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
    if (value == null || remappingFunction == null)
        throw new NullPointerException();
    int hash = hash(key);
    Node<K,V>[] tab; Node<K,V> first; int n, i;
    int binCount = 0;
    TreeNode<K,V> t = null;
    Node<K,V> old = null;
    if (size > threshold || (tab = table) == null ||
        (n = tab.length) == 0)
        n = (tab = resize()).length;
    if ((first = tab[i = (n - 1) & hash]) != null) {
        if (first instanceof TreeNode)
            old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key);
        else {
            Node<K,V> e = first; K k;
            do {
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k)))) {
                    old = e;
                    break;
                }
                ++binCount;
            } while ((e = e.next) != null);
        }
    }
    if (old != null) {
        V v;
        if (old.value != null) {
            int mc = modCount;
            v = remappingFunction.apply(old.value, value);
            if (mc != modCount) {
                throw new ConcurrentModificationException();
            }
        } else {
            v = value;
        }
        if (v != null) {
            old.value = v;
            afterNodeAccess(old);
        }
        else
            removeNode(hash, key, null, false, true);
        return v;
    } else {
        if (t != null)
            t.putTreeVal(this, tab, hash, key, value);
        else {
            tab[i] = newNode(hash, key, value, first);
            if (binCount >= TREEIFY_THRESHOLD - 1)
                treeifyBin(tab, hash);
        }
        ++modCount;
        ++size;
        afterNodeInsertion(true);
        return value;
    }
}

代碼比較長(zhǎng),但是實(shí)現(xiàn)的效果比較容易描述:這個(gè)方法接收3個(gè)參數(shù):key、value、function。

  • 如果key存在,將value按照f(shuō)unction做1次計(jì)算后,更新到Map中
  • 如果key不存在,將key-value放入Map中

這個(gè)方法在某些場(chǎng)景中挺好用的,代碼簡(jiǎn)潔易懂,例如:我們有1個(gè)List,要統(tǒng)計(jì)List中每個(gè)元素出現(xiàn)的次數(shù)。我們要實(shí)現(xiàn)的邏輯是,遍歷List中的每個(gè)元素,如果這個(gè)元素在Map中存在,Map中的值+1;如果不存在,則放入Map中,次數(shù)(值)為1。

private static void testMerge() {
    Map<String, Integer> cntMap = new HashMap<>(8);
    List<String> list = Arrays.asList('apple', 'orange', 'banana', 'orange');

    // 老寫(xiě)法
    for (String item : list) {
        if (cntMap.containsKey(item)) {
            cntMap.put(item, cntMap.get(item) + 1);
        } else {
            cntMap.put(item, 1);
        }
    }

    // 新寫(xiě)法
    for (String item : list) {
        cntMap.merge(item, 1, Integer::sum);
    }
}

可以看到我們使用merge方法的話(huà),只用1行就簡(jiǎn)潔實(shí)現(xiàn)了這個(gè)邏輯。

putIfAbsent

也是一個(gè)見(jiàn)名知意的方法:不存在key或者值為null時(shí),才將鍵值對(duì)放入Map。跟put方法相比,這個(gè)方法不會(huì)直接覆蓋已有的值,在不允許覆蓋舊值的場(chǎng)景使用起來(lái)會(huì)比較簡(jiǎn)潔。

private static void testPutIfAbsent() {
    Map<String, Integer> scoreMap = new HashMap<>(4);
    scoreMap.put('Jim', 88);
    scoreMap.put('Lily', 90);

    // 老寫(xiě)法
    if (!scoreMap.containsKey('Lily')) {
        scoreMap.put('Lily', 98);
    }

    // 新寫(xiě)法
    scoreMap.putIfAbsent('Lily', 98);
}

computer

computer方法需要傳入2個(gè)參數(shù):key、function。主要有3步操作

  • 獲取到key對(duì)應(yīng)的oldValue,可能為null
  • 經(jīng)過(guò)function計(jì)算獲取newValue
  • put(key, newValue)

還是以剛剛統(tǒng)計(jì)單次次數(shù)需求為例,看一下computer的寫(xiě)法:

private static void testComputer() {
    Map<String, Integer> cntMap = new HashMap<>(8);
    List<String> list = Arrays.asList('apple', 'orange', 'banana', 'orange');

    // 老寫(xiě)法
    for (String item : list) {
        if (cntMap.containsKey(item)) {
            cntMap.put(item, cntMap.get(item) + 1);
        } else {
            cntMap.put(item, 1);
        }
    }

    // 新寫(xiě)法
    for (String item : list) {
        cntMap.compute(item, (k, v) -> {
            if (v == null) {
                v = 1;
            } else {
                v += 1;
            }
            return v;
        });
    }
}

computeIfAbsent

看名字就知道是compute方法衍生出來(lái)的方法,這個(gè)方法只在key不存在的時(shí)候,執(zhí)行computer計(jì)算,如果說(shuō)key對(duì)應(yīng)的value存在,就直接返回這個(gè)value。

例如,我們需要計(jì)算斐波那鍥數(shù)列的時(shí)候,可以使用這個(gè)方法來(lái)簡(jiǎn)化代碼:

private static void testComputerIfAbsent() {
    Map<Integer, Integer> fabMap = new ConcurrentHashMap<>(16);
    fabMap.put(0, 1);
    fabMap.put(1, 1);
    System.out.println(fab(5, fabMap));
}

private static Integer fab(Integer index, Map<Integer, Integer> fabMap) {
    return fabMap.computeIfAbsent(index, i -> fab(i - 2, fabMap) + fab(i - 1, fabMap));
}

computeIfPresent

這個(gè)是computeIfAbsent的姊妹方法,區(qū)別在于,這個(gè)方法是只有key存在的時(shí)候,才去執(zhí)行computer計(jì)算和值的更新。

replace

這個(gè)方法的效果是:

  • 如果key存在,則更新值
  • 如果key不存在,什么也不做
責(zé)任編輯:武曉燕 來(lái)源: JAVA日知錄
相關(guān)推薦

2021-09-15 16:05:41

map.putJavaMap

2020-05-20 16:54:47

數(shù)據(jù)分頁(yè)顯示函數(shù)

2022-05-27 08:44:09

springStarter配置

2020-09-18 06:48:21

Python編程語(yǔ)言

2023-10-07 08:59:02

2020-07-03 18:14:20

JavaScript開(kāi)發(fā)技術(shù)

2019-02-28 20:20:43

Python技巧編程語(yǔ)言

2021-10-27 10:07:59

GitHub代碼開(kāi)發(fā)者

2020-02-03 09:29:32

JavaScript代碼斷點(diǎn)

2021-06-11 13:59:22

CSS原子類(lèi)

2022-12-22 08:57:29

Redis數(shù)據(jù)存儲(chǔ)

2023-11-30 08:19:52

偽類(lèi)CSS

2024-07-01 08:31:14

Spring工具類(lèi)代碼

2022-05-20 15:27:41

React工具Vue

2018-06-19 16:25:40

編程語(yǔ)言Python爬蟲(chóng)

2020-03-06 10:54:51

Go語(yǔ)言XML算法

2018-04-18 06:56:26

iPhone手機(jī)電量

2023-11-08 08:43:08

calc函數(shù)CSS

2022-11-28 10:24:10

Spring更新JVM

2020-10-25 08:45:38

IPv6網(wǎng)絡(luò)協(xié)議網(wǎng)絡(luò)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)