zoukankan      html  css  js  c++  java
  • Java基础之:集合——Map——HashMap

    Java基础之:集合——Map——HashMap

    HashMap简单介绍

    1. Map接口的常用实现类:HashMap、Hashtable和Properties。

    2. HashMap是 Map 接口使用频率最高的实现类。

    3. HashMap 是以 key-val 对的方式来存储数据 [案例 Entry ]

    4. key 不能重复,但是是值可以重复,允许使用null键和null值。

    5. 如果添加相同的key , 则会覆盖原来的key-val ,等同于修改.(key不会替换,val会替换)

    6. 与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的.

    7. HashMap没有实现同步,因此是线程不安全的,文档 The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.)

    关于HashMap的案例,就是上一篇博客中描述Map的案例。使用的是HashMap。

    HashMap底层机制

    (k,v)是一个Node节点,实现了Map.Entry<K,V>。

    jdk7.0的hashmap 底层实现[数组+链表], jdk8.0 底层[数组+ 链表/红黑树]

    这里的链表都只有next属性,没有prev属性,即单向链表。

    扩容机制

    table表的扩容机制(即上图中第一行类似数组的表):

    1. HashMap底层维护了Node类型的数组table,默认为null

    2. 当创建对象时,将加载因子(loadfactor)初始化为0.75

    3. 当添加元素时(调用putVal方法),需要通过该元素的哈希值获取在table中的索引。然后判断该索引处是否有元素,如果没有元素直接添加。如果该索引处有元素,需要继续判断是否相等,如果相等则直接覆盖,如果不相等则需要判断此时是树结构还是链表结构,做相应处理。如果添加时发现容量不够就需要扩容。

    4. 如果第一次添加,则需扩容table容量为16,临界值(threshold)为12.(16 * 0.75 = 12)

    5. 即当table表的内容增长到临界值(threshold)时,就会自动扩容。(添加第13个元素进入table表时,扩容)

    6. 如果其他次添加则需扩容table容量到原来的2倍,临界值也改为原来的两倍。(例:第2次扩容,table -> 32 , threshold -> 24)

    table表中单个索引位置的扩容机制(链表/红黑树):

    1. 在table表中,一开始默认是长度为16的数组

    2. 当某一个索引中的元素超过了8时,它优先会选择将长度扩容2倍(即长度为32)的数组。

    3. 它会认为是不是由于数组的长度不够才导致一个索引中元素过多。

    4. 但当它发现长度为32时,某一个索引中的元素还是超过9时,它还是会优先选择将长度再次扩容到2倍(即长度为64)的数组。

    5. 在长度为64的数组中,它发现某一个索引中的元素还是超过10时,它就会对该索引所在的链表转化为红黑二叉树.

    6. 所以在第十一个元素时,才会对该索引所在的链表转化为红黑二叉树.

    测试代码

    import java.util.HashMap;
    public class HashMapTreeNode {
        @SuppressWarnings({ "rawtypes", "unchecked" })
        public static void main(String[] args) {
    ​
            HashMap map = new HashMap();
    ​
            for (int i = 1; i <= 20; i++) {
                User user = new User();
    ​
                map.put(user, user);
    ​
                System.out.println("i =" + i);
            }
        }
    }
    ​
    class User {
    ​
        // 保证每个元素放入同一个索引,将hashcode设置为1
        @Override
        public int hashCode() {
            return 1;
        }
    ​
        // 保证在同一个索引中,每个元素不会因为相同被覆盖,将equles设置为false
        @Override
        public boolean equals(Object obj) {
            return false;
        }
    }

    LinkedHashMap

    LinkedHashMap继承自HashMap,包含了HashMap的所有机制,但不同的是LinkedHashMap是有序的(即添加和取出顺序相同).

    简单案例:

    package class_HashMap;
    ​
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.Set;
    ​
    public class ClassTest01_LinkedHashMap {
    ​
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public static void main(String[] args) {
    ​
            HashMap map = new LinkedHashMap();
            
            map.put("1", "hello01");
            map.put("2", "hello02");
            map.put("3", "hello03");
            map.put("3", "hello05");
            map.put("4", "hello02");
            map.put(null, "hello02");
            map.put("5", null);
            
            //遍历键值对
            Set entrySet = map.entrySet();
            Iterator iterator = entrySet.iterator();
            while(iterator.hasNext()) {
                Object obj = iterator.next();
                Map.Entry node = (Map.Entry)obj;
                System.out.println(node.getKey() + " = " + node.getValue());
            }
            iterator = entrySet.iterator();
        }
    ​
    }

    程序输出:

    1 = hello01

    2 = hello02

    3 = hello05

    4 = hello02

    null = hello02

    5 = null

     

  • 相关阅读:
    cocos2d-x关于CCTableView的“乱序问题”的理解
    线段树
    goldengate 简单配置 oracle to oralce
    iphone缩小uIImage图片
    基本排序算法小结
    Qt4创建工程的几种方法:linux系统
    velocity中的velocityCounter不起作用的原因
    autotools入门笔记(一)
    cp命令的实现
    AutoCompleteTextView输入汉字拼音首字母实现过滤提示(支持多音字)
  • 原文地址:https://www.cnblogs.com/SongHai/p/14195394.html
Copyright © 2011-2022 走看看