简简单单复习一哈HashMap

红烧土豆泥 等级 884 0 0
标签: hashmap

HashMap

可被序列化,线程不安全,允许null值和null键,

安全的Map

Collections.synchronizedMap():

/**
  * Returns a synchronized (thread-safe) map backed by the specified map. In order to guarantee 
  * serial access, it is critical that all access to the backing map is accomplished through the 
  * returned map.
  * It is imperative that the user manually synchronize on the returned map when traversing any of 
  * its collection views via Iterator, Spliterator or Stream:
  *      Map m = Collections.synchronizedMap(new HashMap());
  *          ...
  *      Set s = m.keySet();  // Needn't be in synchronized block
  *          ...
  *      synchronized (m) {  // Synchronizing on m, not s!
  *          Iterator i = s.iterator(); // Must be in synchronized block
  *          while (i.hasNext())
  *              foo(i.next());
  *  }
  */
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
    return new SynchronizedMap<>(m);
}

ConcurrentHashMap:

默认负载因子为0.75,

static final float DEFAULT_LOAD_FACTOR = 0.75f;

默认初始大小为16,

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

当阈值超过16*0.75=12时,会进行扩增操作,每次扩展会进行2的幂扩展,如果当前容量超过了默认容量大小时,最大容量会变成Integer的最大值

最大容量

static final int MAXIMUM_CAPACITY = 1 << 30;

当容量大于等于64时,HashMap会将列表转化为树(bin的值必须大于2且至少为8)

/**
  * The smallest table capacity for which bins may be treeified.
  * (Otherwise the table is resized if too many nodes in a bin.)
  * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts
  * between resizing and treeification thresholds.
  */
static final int MIN_TREEIFY_CAPACITY = 64;

/**
  * Replaces all linked nodes in bin at index for given hash unless
  * table is too small, in which case resizes instead.
  */
final void treeifyBin(Node<K,V>[] tab, int hash) {
        int n, index; Node<K,V> e;
        if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
            resize();
        else if ((e = tab[index = (n - 1) & hash]) != null) {
            TreeNode<K,V> hd = null, tl = null;
            do {
                TreeNode<K,V> p = replacementTreeNode(e, null);
                if (tl == null)
                    hd = p;
                else {
                    p.prev = tl;
                    tl.next = p;
                }
                tl = p;
            } while ((e = e.next) != null);
            if ((tab[index] = hd) != null)
                hd.treeify(tab);
        }
    }

在进行put操作时,如果已经有相同的key,则会将其值进行替换。如果hash值相同会进行内存地址比较,如果地址不相同,则会继续进行非空和equals值比较

    /**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for the key, the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with {@code key}, or
     *         {@code null} if there was no mapping for {@code key}.
     *         (A {@code null} return can also indicate that the map
     *         previously associated {@code null} with {@code key}.)
     */
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

    /**
     * Implements Map.put and related methods.
     *
     * @param hash hash for key
     * @param key the key
     * @param value the value to put
     * @param onlyIfAbsent if true, don't change existing value
     * @param evict if false, the table is in creation mode.
     * @return previous value, or null if none
     */
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; 
        Node<K,V> p; 
        int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }
收藏
评论区

相关推荐

3 手写Java HashMap核心源码
手写Java HashMap核心源码 上一章手写LinkedList核心源码,本章我们来手写Java HashMap的核心源码。 我们来先了解一下HashMap的原理。HashMap 字面意思 hash map,map是映射的意思,HashMap就是用hash进行映射的意思。不明白?没关系。我们来具体讲解一下HashMap的原理。 HashMap
HashMap的理解
HashMap在Map.Entry静态内部类实现中存储keyvalue对。HashMap使用哈希算法,在put和get方法中,它使用hashCode()和equals()方法。当我们通过传递keyvalue对调用put方法的时候, HashMap使用Key hashCode()和哈希算法来找出存储keyvalue对的索引。Entry存储在LinkedL
拿下面试!HashMap源码解析!!
拿下面试!HashMap源码解析!! HashMap的设计思想 HashMap的底层结构 本文主要是讲解jdk1.8中的HashMap源码,会对jdk1.7中的HashMap做一些简单的讲解用来和jdk1.8中的HashMap进行对比。 我们先通过下图来理解HashMap的底层结构: (https
简简单单复习一哈HashMap
HashMap可被序列化,线程不安全,允许null值和null键,安全的MapCollections.synchronizedMap(): / Returns a synchronized (threadsafe) map backed by the specified map. In order to guarantee s
Java 之 HashMap 集合
一、HashMap 概述 ============ java.util.HashMap<k,v> 集合 implements Map<k,v> 接口 **HashMap 集合的特点**: 1、HashMap 集合底层是哈希表:**查询速度特别的快** JDK 1.8 之前:数组+单向链表 JDK 1.8 之后:数组+单向链表 | 红黑树(
Java集合之Map接口
Map使用键值对来存储数据,将键映射到值对象,一个映射不能包含重复的键,每一个键最多只能映射到一个值。Map接口的具体实现类:HashMap,Hashtable,TreeMap,LinkedHashMap   **1)HashMap**   基于哈希表(哈希表学习地址)的Map接口实现。允许使用null值和null键,不保证映射的顺序,特别是不保证顺序恒
java基础之HashMap——第一节
前两篇文章粗略的介绍了java中的List,既然已经讲了两种java的数据结构,那么这篇就接着讲java中的数据结构了。 HashMap作为最常用的一种Map,就放在第一个讲了。 Map是一个较复杂的结构,本身内容不是太难,但是各个实现的思想完全不同,所以可能关于Map的介绍会比较多,源码分析会放在后边,主要是算法分析。 要讲HashM
java容器之HashMap
HashMap采用了数组和链表的数据结构,能在查询和修改方便继承了数组的线性查找和链表的寻址修改,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的。 解决哈希冲突的三个方法: a.开放定址法     又被称为再散列法,包括线性探测再散列、二次探测再散列、伪随机探测再散列 b.再哈希法     地址冲突后,对哈希结果再次进行哈希,直到
Collectors.groupingBy分组后的排序问题
默认groupingBy代码里会生成一个HashMap(hashMap是无序的,put的顺序与get的顺序不一致) * HashMap是无序的,HashMap在put的时候是根据key的hashcode进行hash然后放入对应的地方。所以在按照一定顺序put进HashMap中,然后遍历出HashMap的顺序跟put的顺序不同(除非在put的时候key已
GridView实现九宫格
GridView gv=(GridView)findViewById(R.id.g1);         ArrayList<HashMap<String,Object>>data=new ArrayList<HashMap<String, Object>>();         for(int i=0;i<images.length;i++)
HashMap 为什么会导致 CPU 100%?文章看不懂?来看这个视频吧!——面试突击 006 期
> 无论是在实际工作中还是在面试中,HashMap 无疑是使用频率最高的知识点之一,所以我们需要搞懂每一个关于 HashMap 的知识点才行。 哈喽,大家好,我是老王,欢迎来到 Java 面试突击,我们今天来开始第 6 期的内容。 本期的问题是:HashMap 为什会导致 CPU 运行 100%?这是一个比较常见的经典问题了,但是有很多人读者朋友给我反馈
HashMap 初始化时赋值
一般初始化一个map并且给map赋值的写法: HashMap<String, String> map = new HashMap<String, String>(); map.put("name", "test"); map.put("age", "20"); 但是我想在初始化的时候就直接给map中set值。
HashMap 的 defaultLoadFactor 的一种推导计算思路
1\. 为啥需要 defaultLoadFactor -------------------------- 现在主流的 HashMap,一般的实现思路都是开放地址法+链地址法的方式来实现。 ![image](https://zhxhash-blog.oss-cn-beijing.aliyuncs.com/Project%20Reactor/HashMap/
HashMap源码分析 JDK1.8
> 本文按以下顺序叙述: * HashMap的感性认识. * 官方文档中对HashMap介绍的解读. * 到源码中看看HashMap这些特性到底是如何实现的. > 把源码啃下来有一种很爽的感觉, 相信你读完后也能体会到~ 如发现有误, 欢迎指出. * * * <h3 id=1>在开始之前, 先通过图例对HashMap建立感性认识</h3>
HashMap的实现原理
HashMap概述 ========= HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。 HashMap的数据结构 ============ 在Java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数