欢迎光临散文网 会员登陆 & 注册

java双例集合HashMap类

2022-07-27 15:56 作者:虚云幻仙  | 我要投稿

/**
* Map双例集合 存储格式为KV键值对 K(key)不可重复  V(value)可重复 Map接口常用实现类HashMap和TreeMap
* value为要存储的元素
*/

public class TestHashMap {
   public static void main(String[] args) {
       Map<String,Integer> hm = new HashMap<>();
       //泛型字符有K/V两个 需要分别设定 设定类型可重复 第一个泛型K代表key 第二个泛型V代表value
       Integer oldscore = hm.put("wang",59);
       //Map接口添加元素的方法.put 将KV对传参 返回类型V 添加元素时会对key进行判断 如果Map内没有该key 则存储该KV对并返回null
       System.out.println(oldscore);
       //结果null
       oldscore = hm.put("wang",61);
       //如果Map内已经有该key 则将新的value覆盖掉原来的  将原来的value返回 Map内不生成新的KV对
       System.out.println(oldscore);
       //结果59 新的成绩61将59覆盖
       System.out.println(hm);
       //结果{wang=61} 只有一个KV对 wang的成绩被更改为61
       System.out.println(hm.get("wang"));
       //.get(K) 返回对应的value 结果61
       System.out.println(hm.get("aaaaa"));
       //集合中没有找到相同的key时会返回null
       hm.put("zhao",80);
       for (String key:hm.keySet()){
           //.keySet()返回包含所有key的Set集合 通过for-each遍历key
           System.out.println(hm.get(key));
           //用每个key传参进.get(K)方法拿到value 结果61 80
       }
       Set<String> keys = hm.keySet();
       //返回key的Set集合 因为key泛型设定为String 引用类型的Set泛型也要设定为String

       Set<Map.Entry<String,Integer>> entries = hm.entrySet();
       //Map接口的.entrySet()返回包含所有Map.Entry对象的集合  Entry<K,V>接口为Map<K,V>接口的内部接口 通过Map.调用  entry条目
       //集合内每一个Entry<K,V>对象表示一个KV对 集合的存储类型为Entry Entry的KV类型同Map中的设定
       //所以集合的泛型Set<Map.Entry>  为通过Map调用的子接口Entry类型   而Entry的泛型 Entry<String,Integer> 和调用.entrySet()的Map容器对象保持一致
       //合起来为Set<Map.Entry<String,Integer>> 引用类型
       //如同Map hm = new HashMap一样  Entry接口同样为编译类型 实际存储为Entry的实现类

       for (Map.Entry<String,Integer> entry:entries){
           //Set<Map.Entry<String,Integer>>集合中的元素为Map.Entry<String,Integer> for-each需要设定同类型的引用变量来遍历
           System.out.println(entry.getKey());
           System.out.println(entry.getValue());
           //通过.getKey().getValue()调用每个entry内的key和value
           System.out.println(entry);
           //直接打印entry结果为wang=61
       }
       System.out.println(hm.entrySet());
       //直接打印entry集合返回数组 结果为[wang=61, zhao=80]
       System.out.println(hm);
       //结果为{wang=61, zhao=80}

       Map<String,Integer> hm2 = new HashMap<>();
       hm2.put("zhao",40);
       hm2.put("sun",99);
       hm.putAll(hm2);
       //.putAll(Map m) 并集 将m集合中的元素放进this集合中 如果this中已有部分key 会被m中的KV覆盖 无返回值
       System.out.println(hm);
       //结果为{wang=61, zhao=40, sun=99} hm2的zhao=40覆盖了hm的zhao=80

       Integer value = hm.remove("wang");
       //.remove(K key) 传参key 删除对应的KV对 返回被删除的value
       for (String key :
               hm.keySet()) {
           System.out.print(key+"="+hm.get(key)+",");
       }
       //结果为zhao=40,sun=99,
       System.out.println(value);
       //结果为61
       System.out.println(hm.containsKey("wang"));
       //.containsKey(K key)查询集合中是否包含key 返回类型boolean 因为wang已经被remove 集合中不存在wang返回false
       System.out.println(hm.containsValue(99));
       //.containsValue(V value)查询集合中是否包含value 返回类型boolean 结果为true
   }
}
/* ctrl+左键查看HashMap源码
public class HashMap<K,V> extends AbstractMap<K,V>
   implements Map<K,V>, Cloneable, Serializable {
   //泛型类HashMap<K,V>实现泛型接口Map<K,V>
   static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
   //initial初始的 默认初始容量 1左位移4为1*2^4=16 HashMap集合的哈希表数组的初始长度为16 数组的长度必须为2的n次幂
   //HashMap延迟初始化 当new HashMap()无参时 哈希表数组为{} 初次.put()添加结点时会初始化长度

   static final int MAXIMUM_CAPACITY = 1 << 30;
   //maximum最大 哈希表数组的最大长度为2^30 int类型的取值范围为-2^31到2^31-1
   static final float DEFAULT_LOAD_FACTOR = 0.75f;
   //load负载 factor因子 0.75默认double类型 加f转为float类型 当容器的占用率达到75%时会对哈希表数组进行扩容
   static final int TREEIFY_THRESHOLD = 8;
   //tree指红黑树 threshold阈 当哈希桶/单向链表的size达到8 并且哈希表数组的长度达到64时 会将哈希桶从链表转变为红黑树
   static final int UNTREEIFY_THRESHOLD = 6;
   //当红黑树结点的size降到6时 会将红黑树变回单向链表
   static final int MIN_TREEIFY_CAPACITY = 64;
   //只有当哈希表数组的长度达到64之后 单向链表的size达到8才会转变为红黑树

   static class Node<K,V> implements Map.Entry<K,V> {
   //静态内部类 node结点 实现Map.Entry 当HashMap集合调用.entrySet()返回的Map.Entry集合 Map.Entry为编译类型 运行时类型为HashMap.Node<K,V>
   //即实际返回的是结点的集合 Node为单向链表的结点

       final int hash;
       //hash值决定结点存放在哈希表的哪个位置
       final K key;
       //集合中存储的每一对KV的key实际存放在node结点的key中
       V value;
       //value存放KV对的元素 是真正要存放的对象
       Node<K,V> next;
       //直接后继结点 单向链表没有直接前驱结点指针prev 链表表尾结点的next=null
       public final K getKey()        { return key; }
       public final V getValue()      { return value; }
       //Node实现Map.Entry接口的getKey()和getValue()方法 实际调用每个entry.getKey()时即调用Node重写的方法

   //回到HashMap类
   transient Node<K,V>[] table;
   //table即哈希表数组 数组类型为结点 在表中存放的是单向链表的表头结点 同index的结点通过.next单向链接 当添加结点时会将新结点链到表尾
   //当删除结点时会将其前驱结点.next变更为删除结点的后继结点 跳过要删除的结点完成删除 删除表头结点会将表头变更为表头结点的后继结点


   static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
   //树结点 用于红黑树的结点 父类的父类是HashMap.Node类 通过继承Node类实现链表结点和树结点的转换
       TreeNode<K,V> parent;
       //树结点的父结点
       TreeNode<K,V> left;
       //树结点的左子树结点
       TreeNode<K,V> right;
       //右子树结点
       TreeNode<K,V> prev;    // needed to unlink next upon deletion
       boolean red;
       //boolean类型 用于表示树结点为红色还是黑色 boolean只占1bit
       TreeNode(int hash, K key, V val, Node<K,V> next) {
           super(hash, key, val, next);
       }

   transient int size;
   //集合中结点的总数
   int threshold;
   //阈值,为数组容量capacity*负载因子load factor的值,当size达到阈值时会对数组进行扩容

   public HashMap() {
       this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
   }
   //无参构造器,new HashMap<>()哈希表table没有初始化容量,默认初始化为null
*/

java双例集合HashMap类的评论 (共 条)

分享到微博请遵守国家法律