ConcurrentHashMap 源码分析10函数篇之 Iterator、Spliterator、keySet

此篇相关的类在 02 篇。

1. keys()

  • 获取 key 值的迭代器
public Enumeration<K> keys() {
    Node<K,V>[] t;
    int f = (t = table) == null ? 0 : t.length;
    return new KeyIterator<K,V>(t, f, 0, f, this);
}

2. keySet()、keySet(V mappedValue)

  • 获取 key 值的视图
public KeySetView<K,V> keySet() {
    KeySetView<K,V> ks;
    return (ks = keySet) != null ? ks : (keySet = new KeySetView<K,V>(this, null));
}

public KeySetView<K,V> keySet(V mappedValue) {
    if (mappedValue == null)
        throw new NullPointerException();
    return new KeySetView<K,V>(this, mappedValue);
}

3. values()

  • 获取 value 值的视图
public Collection<V> values() {
    ValuesView<K,V> vs;
    return (vs = values) != null ? vs : (values = new ValuesView<K,V>(this));
}

4. elements()

  • 获取 value 值的迭代器
public Enumeration<V> elements() {
    Node<K,V>[] t;
    int f = (t = table) == null ? 0 : t.length;
    return new ValueIterator<K,V>(t, f, 0, f, this);
}

5. entrySet()

  • 获取键值对的视图
public Set<Map.Entry<K,V>> entrySet() {
    EntrySetView<K,V> es;
    return(es = entrySet) != null ? es : (entrySet = new EntrySetView<K,V>(this));
}

6. 小总结

import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentHashMap.KeySetView;

public class ConcurrentHashMapTest09 {
    public static void main(String[] args) {
        ConcurrentHashMap<Integer, Integer> concurrentHashMap = new ConcurrentHashMap<>();
        for(int i = 1; i <= 20; i++) {
            concurrentHashMap.put(i, i);
        }
        System.out.println("now concurrentHashMap: " + concurrentHashMap);
        Enumeration<Integer> keys = concurrentHashMap.keys();
        System.out.println("Enumeration --> keys: " + keys);
        long start01 = System.currentTimeMillis();
        System.out.print("Enumeration 遍历 keys 元素: ");
        while (keys.hasMoreElements()) {
            System.out.print(keys.nextElement() + "\t");
        }
        long end01 = System.currentTimeMillis();
        System.out.println();
        System.out.println("Enumeration 耗时: " + (end01 - start01) + "ms");

        Iterator<Integer> iterator = concurrentHashMap.keySet().iterator();
        long start02 = System.currentTimeMillis();
        System.out.print("Iterator 遍历 keySet 元素: ");
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + "\t");
        }
        System.out.println();
        long end02 = System.currentTimeMillis();
        System.out.println("Iterator 耗时: " + (end02 - start02) + "ms");

        KeySetView<Integer, Integer> keySet1 = concurrentHashMap.keySet(5);
        System.out.println("keySet1: " + keySet1);
        Enumeration<Integer> elements = concurrentHashMap.elements();
        System.out.println("Enumeration --> elements: " + elements);
        Collection<Integer> values = concurrentHashMap.values();
        System.out.println("values: " + values);

        Set<Entry<Integer, Integer>> entries = concurrentHashMap.entrySet();
        System.out.println("entries: " + entries);
    }
}

在这里插入图片描述

具有 迭代器Iterator,肯定少不了 分解迭代器 Spliterator 的使用。

import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentHashMap.KeySetView;

public class ConcurrentHashMapTest10 {
    public static void main(String[] args) {
        ConcurrentHashMap<Integer, Integer> concurrentHashMap = new ConcurrentHashMap<>();
        for(int i = 1; i <= 20; i++) {
            concurrentHashMap.put(i, i);
        }
        System.out.println("now concurrentHashMap: " + concurrentHashMap);

        KeySetView<Integer, Integer> keySet = concurrentHashMap.keySet(5);
        System.out.println("keySet: " + keySet);
        Spliterator<Integer> keySpliterator = keySet.spliterator();
        keySpliterator.tryAdvance((key)-> {
            System.out.println("keySpliterator tryAdvance: " + key);
        });
        Spliterator<Integer> keySpliterator01 = keySpliterator.trySplit();
        System.out.print("keySpliterator forEachRemaining: ");
        keySpliterator.forEachRemaining((key) -> System.out.print(key + "\t"));
        System.out.println();
        System.out.print("keySpliterator01 forEachRemaining: ");
        keySpliterator01.forEachRemaining((key) -> System.out.print(key + "\t"));
        System.out.println();
        System.out.println("===================================");

        Collection<Integer> values = concurrentHashMap.values();
        System.out.println("values: " + values);
        Spliterator<Integer> valueSpliterator = values.spliterator();
        valueSpliterator.tryAdvance((key)-> {
            System.out.println("values tryAdvance: " + key);
        });
        Spliterator<Integer> valueSpliterator01 = valueSpliterator.trySplit();
        System.out.print("valueSpliterator forEachRemaining: ");
        valueSpliterator.forEachRemaining((key) -> System.out.print(key + "\t"));
        System.out.println();
        System.out.print("valueSpliterator01 forEachRemaining: ");
        valueSpliterator01.forEachRemaining((key) -> System.out.print(key + "\t"));
        System.out.println();
        System.out.println("===================================");

        Set<Entry<Integer, Integer>> entries = concurrentHashMap.entrySet();
        System.out.println("entries: " + entries);
        Spliterator<Entry<Integer, Integer>> entrySpliterator = entries.spliterator();
        entrySpliterator.tryAdvance((entry)-> {
            System.out.println("entries tryAdvance: " + entry);
        });
        Spliterator<Entry<Integer, Integer>> entrySpliterator01 = entrySpliterator.trySplit();
        System.out.print("entrySpliterator forEachRemaining: ");
        entrySpliterator.forEachRemaining((entry) -> System.out.print(entry + "\t"));
        System.out.println();
        System.out.print("entrySpliterator01 forEachRemaining: ");
        entrySpliterator01.forEachRemaining((entry) -> System.out.print(entry + "\t"));
        System.out.println();

    }
}
  • trySplit() 是剩下未遍历的桶位对半分。执行完 tryAdvance 后,剩下的桶位下标为 [2, 32),分割时 mid = (2 + 32) >> 1 = 17,则两个分解迭代器的下标分别为 [2,17),[17,32]。所以 Spliterator01 输出为 17 - 20。
    在这里插入图片描述

7. newKeySet()

  • 静态方法,初始化一个ConcurrentHashMap 值为 true 的 keySet 视图
public static <K> KeySetView<K,Boolean> newKeySet() {
    return new KeySetView<K,Boolean>
        (new ConcurrentHashMap<K,Boolean>(), Boolean.TRUE);
}
/* initialCapacity:初始化容量 */
public static <K> KeySetView<K,Boolean> newKeySet(int initialCapacity) {
    return new KeySetView<K,Boolean>
        (new ConcurrentHashMap<K,Boolean>(initialCapacity), Boolean.TRUE);
}
  • 代码演示
import java.lang.reflect.Field;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentHashMap.KeySetView;

public class ConcurrentHashMapTest11 {
    public static void main(String[] args) throws Exception {
        /* 默认初始化容量为 DEFAULT_CAPACITY = 16 */
        KeySetView<Object, Boolean> keySetView = ConcurrentHashMap.newKeySet();
        /* 初始化容量计算公式 tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1)
        * tableSizeFor(30 + 30 >> 1 + 1) = tableSizeFor(45) = 64  */
        KeySetView<Object, Boolean> keySetView01 = ConcurrentHashMap.newKeySet(30);
        for(int i = 1; i <= 10; i++) {
            keySetView.add(i);
            keySetView01.add(i);
        }
        Class<? extends KeySetView> keySetClass = keySetView.getClass();
        Class<? extends KeySetView> keySetClass01 = keySetView01.getClass();
        Field value = keySetClass.getDeclaredField("value");
        Field value01 = keySetClass01.getDeclaredField("value");
        value.setAccessible(true);
        value01.setAccessible(true);
        System.out.println("KeySetView 的 value 值" + value.get(keySetView));
        System.out.println("KeySetView01 的 value 值" + value01.get(keySetView01));
        Class<?> keySetClassSuperclassClass = keySetClass.getSuperclass();
        Class<?> keySetClassSuperclassClass01 = keySetClass01.getSuperclass();
        Field map = keySetClassSuperclassClass.getDeclaredField("map");
        Field map01 = keySetClassSuperclassClass01.getDeclaredField("map");
        map.setAccessible(true);
        map01.setAccessible(true);
        ConcurrentHashMap concurrentHashMap = (ConcurrentHashMap) map.get(keySetView);
        ConcurrentHashMap concurrentHashMap01 = (ConcurrentHashMap) map01.get(keySetView01);
        System.out.println("keySetClassSuperclassClass 的 map 值" + concurrentHashMap);
        System.out.println("keySetClassSuperclassClass 的 map01 值" + concurrentHashMap01);

        System.out.println("================ 以下代码体现初始化容量的差别 ===============");
        Field table = concurrentHashMap.getClass().getDeclaredField("table");
        Field table01 = concurrentHashMap01.getClass().getDeclaredField("table");
        table.setAccessible(true);
        table01.setAccessible(true);
        Object[] objects = (Object[]) table.get(concurrentHashMap);
        Object[] objects01 = (Object[]) table01.get(concurrentHashMap01);
        System.out.println("keySetClassSuperclassClass 的 map 的 table.length(): " + objects.length);
        System.out.println("keySetClassSuperclassClass 的 map01 的 table01.length(): " + objects01.length);

    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ConcurrentHashMap是Java中的一个并发容器,用于在多线程环境中安全地存储和访问键值对。它使用了一些特殊的技术来提高其并发性能。 ConcurrentHashMap分析可以从几个关键点开始。首先,它使用了大量的CAS(Compare and Swap)操作来代替传统的重量级锁操作,从而提高了并发性能。只有在节点实际变动的过程中才会进行加锁操作,这样可以减少对整个容器的锁竞争。 其次,ConcurrentHashMap的数据结构是由多个Segment组成的,每个Segment又包含多个HashEntry。这样的设计使得在多线程环境下,不同的线程可以同时对不同的Segment进行操作,从而提高了并发性能。每个Segment都相当于一个独立的HashMap,有自己的锁来保证线程安全。 在JDK1.7版本中,ConcurrentHashMap采用了分段锁的设计,即每个Segment都有自己的锁。这样的设计可以在多线程环境下提供更好的并发性能,因为不同的线程可以同时对不同的Segment进行读写操作,从而减少了锁竞争。 总的来说,ConcurrentHashMap通过使用CAS操作、分段锁以及特定的数据结构来实现线程安全的并发访问。这使得它成为在多线程环境中高效地存储和访问键值对的选择。123 #### 引用[.reference_title] - *1* [ConcurrentHashMap 码解析](https://blog.csdn.net/Vampirelzl/article/details/126548972)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] - *2* *3* [ConcurrentHashMap分析](https://blog.csdn.net/java123456111/article/details/124883950)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值