zoukankan      html  css  js  c++  java
  • 十一(二)、集合之Map

    一、Map的实现类的结构

      Map:双列数据,存储key--value对的数据 -----类似于高中的函数 y = f(x)

    使用Set存储所有的key,key所在的类要重写equals()和hashCode()的方法;(以HashMap为例说的)

      1、HashMap:

    • 作为Map的主要实现类;线程不安全,可以存储null的key和value;
    • HashMap的底层:数组+链表(jdk7及之前)

         数组+链表+红黑树(jdk8)

    • 子类:LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历;

       a、原因是:在原有的hashmap底层结构基础上,添加了一堆指针,指向前一个和后一个元素

       b、对于频繁的遍历操作,此类执行效率更高;

    测试代码:

     1 @Test
     2     public void test() {
     3         Map hashMap = new HashMap();
     4         hashMap.put(null, null);
     5         hashMap.put(123, "AA");
     6         hashMap.put(456, "BB");
     7         hashMap.put(789, "CC");
     8         System.out.println(hashMap);
     9         
    10         LinkedHashMap linkedHashMap = new LinkedHashMap();
    11         linkedHashMap.put(null, null);
    12         linkedHashMap.put(123, "AA");
    13         linkedHashMap.put(456, "BB");
    14         linkedHashMap.put(789, "CC");
    15         System.out.println(linkedHashMap);
    16         
    17         Hashtable hashtable = new Hashtable();
    18 //        hashtable.put(null, null);//会报错哦
    19         
    20     }

    这里的

    System.out.println(hashMap),无序输出;
    System.out.println(linkedHashMap);按插入属性输出

      2、TreeMap:

    • 保证按照添加的key value 对进行排序,实现排序遍历;(需要向tree添加 key-value ,要求key必须是同一个类的对象
    • 此时使用考虑key的自然排序和定制排序;
    • 底层使用红黑树;

      3、Hashtable:

    • 作为古老的实现类;线程安全;不可以存储null的key和value;
    • 子类:Properties:常用来处理配置文件; key&value 都是Strin 

      4.思维导图:

      脑图查看地址https://www.cnblogs.com/lixiuming521125/p/14626222.html

    二、Map结构的理解

      1、Map中的key:无序的、不可重复的:

        使用Set存储所有的key,key所在的类要重写equals()和hashCode()的方法;(以HashMap为例说的)

      2、Map中的value:无序的可重复的;

        使用Collection存储所有值;所在类需要重写equals()方法;

      3、一个key-value 构成了一个Entry对象

      4、Map中的Entry:无序的、不可重复的,使用Set存储所有的entry;

      

    三、HashMap底层实现原理:(以jdk7说明)

    1、实现原理:

    1  HashMap map = new HashMap();//在实例化以后,底层创建了长度为16的一维数组Entry[] table;
    2 
    3   ...//可能已经指向过多次put
    4 
    5   map.put(key1,value1);

      首先:调用key1所在类的hashCode()计算key1的哈希值;此哈希值经过某种算法计算后,得到在Entry数组中的存放位置;

        如果此位置上的数据为空;此时key1,value1的添加成功;--------情况1

        如果此位置上的数据不为空,(意味着此位置存在或一个或多个数据(以链表形式存在))

          比较key1和已经存在的一个或者多个数据的哈希值

           如果key1和已经存在的一个或多个数据的哈希值不同,则此时key1,value1的添加成功;--------情况2

           如果key1和已经存在的某个数据(key2-value2)的哈希值相同,则调用key1所在类的equals方法,

      若果返回true,则value1替换

      若返回false,则key1,value1的添加成功;--------情况3

      对于添加成功的情况2和情况3而言,key1-value1与已经存在指定位置上索引位置上数据以链表形式存储;

      

      在不断添加的过程中,会涉及到扩容问题;默认的扩容方式:当超出临界值且存放位置不为空,扩容为原来容量的2倍,并且将原来的数据复制过来;

      

      jdk8,相较于jdk7;

      1.new HashMap()底层没有创建一个长度为16的数组

      2.jdk8底层的数组是:Node[] 而非Entry[];

      3.首次调用put方法,底层创建长度为16的数组;

      4.jdk7底层结构只有:数组+链表,jdk8中底层结构:数组+链表+红黑树

      当数组的某一个索引位置上的元素以及链表形式存在的数据个数》8且当数组的长度>64时,

      此索引位置上的说有数据改为红黑树存储;

      2、各常量说明:

    •   DEFAULT_INITIAL_CAPACITY:HashMap的默认容量16;
    •   DEFAULT_LOAD_FACTOR;HashMap默认的加载因子:0.75
    •   threshold:扩容的临界值:DEFAULT_LOAD_FACTORDEFAULT_INITIAL_CAPACITY  0.7516 = 12
    •   TREEIFY_THRESHOLD:桶中链表长度大于该默认值,转换为红黑树:8
    •   MIN_TREEIFY_CAPACITY:桶中的node被树话最小的hash表容量:64

    四、linkedHashMap的底层实现原理

    • 对于频繁的添加查找元素,可以使用linkedHashMap;  
    • 可以按插入顺序输出;

      源码中:没有put 方法,因为继承了HashMap;

    1   public class LinkedHashMap<K,V>
    2 
    3     extends HashMap<K,V>
    4 
    5     implements Map<K,V> 
    6 
    7     

    所以这里的put还是HashMap的put方法

    linkedHashMap重写了    newNode

     1 Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
     2 
     3         LinkedHashMap.Entry<K,V> p =
     4 
     5             new LinkedHashMap.Entry<K,V>(hash, key, value, e);
     6 
     7         linkNodeLast(p);
     8 
     9         return p;
    10 
    11     }
     1   static class Entry<K,V> extends HashMap.Node<K,V> {
     2 
     3         Entry<K,V> before, after;//这里能够记录添加元素的先后顺序;
     4 
     5         Entry(int hash, K key, V value, Node<K,V> next) {
     6 
     7             super(hash, key, value, next);
     8 
     9         }
    10 
    11     }

      

    五、Map的常用方法:

      1.添加 删除 修改操作

    1.   Object put(Object key,Object value);将指定的key-value(添加、修改)到当前map对象中;
    2.   void putAll(Map m),将m中所有的 key-value对放入当前map中
    3.   Object remove(Object key),移除指定的key-value对,并返回value;
    4.   void clear();清空当前map中的所有数据

      2、元素查询的操作

    1.   Object get(Object key):获取指定key 对应的value
    2.   boolean containsKey(Object key),是否包含指定的key
    3.   boolean containsValue(Object value):是否包含指定的value;
    4.   int size():返回map中key-value对的个数;
    5.   boolean isEmpty():判断当前map是否为空;
    6.   boolean equals(Object obj):判断当前map和参数对象obj是否相等 

      3.元素操作的方法:

    1.   Set keySet();返回左右可以构成的Set集合
    2.   Collection values();返回所有values构成的Collection集合;
    3.   Set entrySet():随会所有key-value对构成的Set集合;

       总结常用方法:

    •    添加:put(Object key,Object value)
    •    删除:remove(Object key)
    •    修改:put(Object key,Object value)
    •    查询:get(Object key)
    •    遍历:keySet();
    •    长度 size()
    •    遍历 

       key-value 的遍历:entrySet()的遍历 or keySet()+get(Object key)来遍历

       key的遍历:keySet()

       value的遍历:values();

    这里需要注意的是values()是由Collection存放,如果想取出所有值,建议遍历,将每个ele add到List<Ele>中

    常用方法测试:

     1 /**
     2      *1.添加 删除 修改操作
     3      * Object put(Object key,Object value);将指定的key-value(添加、修改)到当前map对象中;
     4      * void putAll(Map m),将m中所有的 key-value对放入当前map中
     5      * Object remove(Object key),移除指定的key-value对,并返回value;
     6      * void clear();清空当前map中的所有数据 
     7      * 2、元素查询的操作
     8      * Object get(Object key):获取指定key 对应的value
     9      * boolean containsKey(Object key),是否包含指定的key
    10      * boolean containsValue(Object value):是否包含指定的value;
    11      * int size():返回map中key-value对的个数;
    12      * boolean isEmpty():判断当前map是否为空;
    13      * boolean equals(Object obj):判断当前map和参数对象obj是否相等;
    14      *  Set keySet();返回左右可以构成的Set集合
    15      * Collection values();返回所有values构成的Collection集合;
    16      * Set entrySet():随会所有key-value对构成的Set集合;
    17      * 
    18      */
    19     @Test
    20     public void test1() {
    21         Map hashMap = new HashMap();
    22         //Object put(Object key,Object value)来添加元素
    23         hashMap.put(null, null);
    24         hashMap.put(123, "AA");
    25         hashMap.put(456, "BB");
    26         hashMap.put(789, "CC");
    27         System.out.println("hashMap:"+hashMap);
    28         // void putAll(Map m),将m中所有的 key-value对放入当前map中
    29         Map newHashMap = new HashMap();
    30         newHashMap.putAll(hashMap);
    31         System.out.println("newHashMap:"+newHashMap);//所有hashMap中的数据放入了newHashMap中;
    32         
    33         System.out.println("newHashMap的equals方法:"+newHashMap.equals(hashMap));
    34         
    35         hashMap.remove(123);
    36         System.out.println("hashMap的remove方法:"+hashMap);
    37         
    38         hashMap.clear();//
    39         System.out.println("hashMap的clear方法:"+hashMap);//{},而不是null
    40         
    41         Object obj = newHashMap.get(123);
    42         System.out.println("newHashMap的get方法:"+obj);
    43         
    44         boolean flag1 = newHashMap.containsKey("AA");
    45         System.out.println("newHashMap的containsKey方法:"+flag1);
    46         
    47         boolean flag2 = newHashMap.containsValue("AA");
    48         System.out.println("newHashMap的containsValue方法:"+flag2);
    49         
    50         System.out.println("newHashMap的size方法:"+newHashMap.size());
    51         
    52         System.out.println("newHashMap的isEmpty方法:"+newHashMap.isEmpty());//就是判断size()是否为0
    53         
    54         System.out.println("newHashMap的keySet方法:"+newHashMap.keySet());
    55         //遍历所有的key
    56         Set keySet = newHashMap.keySet();
    57         Iterator iterator = keySet.iterator();
    58         while(iterator.hasNext()) {
    59             System.out.println("遍历所有的key:"+iterator.next());
    60         }
    61         
    62         System.out.println("newHashMap的values方法:"+newHashMap.values());
    63         //遍历所有的values
    64         Collection values = newHashMap.values();
    65         Iterator iterator2 = values.iterator();
    66         while(iterator2.hasNext()) {
    67             System.out.println("遍历所有的values:"+iterator2.next());
    68         }
    69         
    70         System.out.println("newHashMap的entrySet方法:"+newHashMap.entrySet());
    71         //遍历所有的entrySet
    72         Set entrySet = newHashMap.entrySet();
    73         Iterator iterator3 = entrySet.iterator();
    74         while(iterator3.hasNext()) {
    75             Entry entry = (Entry) iterator3.next();
    76             System.out.println(entry.getKey()+"--->"+entry.getValue());//输出键值对;
    77         }
    78         
    79         //输出键值对
    80         Set keySet1 = newHashMap.keySet();
    81         Iterator iterator4 = keySet.iterator();
    82         while(iterator4.hasNext()) {
    83             Object key = iterator4.next();
    84             System.out.println(key+"--->"+newHashMap.get(key));//输出键值对;
    85         }
    86         
    87     }

    六、TreeMap中的排序:

    1.    需要向tree添加 key-value ,要求key必须是同一个类的对象
    2.    因为要按照key 排序(自然排序、定制排序)

    测试代码:

     1 //定制排序
     2     @Test
     3     public void test2() {
     4         Comparator com = new Comparator<Person>() {
     5 
     6             @Override
     7             public int compare(Person o1, Person o2) {
     8                 if(o1.getAge()-o2.getAge()>=0) {
     9                     return 1;
    10                 }
    11                 return -1;
    12             }
    13         };
    14         TreeMap treeMap = new TreeMap(com);
    15         treeMap.put( new Person("joy",30), new Object());
    16         treeMap.put(new Person("tom",31), new Object());
    17         treeMap.put(new Person("lucy",18), new Object());
    18         treeMap.comparator();
    19         Iterator iterator = treeMap.keySet().iterator();
    20         while(iterator.hasNext()) {
    21             System.out.println(iterator.next());
    22         }
    23         
    24     }
    25     
    26     //自然排序;
    27     @Test
    28     public void test3() {
    29         TreeMap treeMap = new TreeMap();
    30         treeMap.put( new Person("joy",30), new Object());
    31         treeMap.put(new Person("tom",31), new Object());
    32         treeMap.put(new Person("lucy",18), new Object());
    33         Iterator iterator = treeMap.keySet().iterator();
    34         while(iterator.hasNext()) {
    35             System.out.println(iterator.next());
    36         }
    37         
    38     }

    附:

     1 package collection;
     2 
     3 public class Person implements Comparable {
     4 
     5     private String name;
     6     private int age;
     7     public String getName() {
     8         return name;
     9     }
    10     public void setName(String name) {
    11         this.name = name;
    12     }
    13     public int getAge() {
    14         return age;
    15     }
    16     public void setAge(int age) {
    17         this.age = age;
    18     }
    19     public Person(String name, int age) {
    20         super();
    21         this.name = name;
    22         this.age = age;
    23     }
    24     public Person() {
    25         super();
    26     }
    27     @Override
    28     public String toString() {
    29         return "Person [name=" + name + ", age=" + age + "]";
    30     }
    31     @Override
    32     public int hashCode() {
    33         final int prime = 31;//这里使用31为了减少冲突、提高算法效率
    34         int result = 1;
    35         result = prime * result + age;
    36         result = prime * result + ((name == null) ? 0 : name.hashCode());
    37         return result;
    38     }
    39     @Override
    40     public boolean equals(Object obj) {
    41         if (this == obj)
    42             return true;
    43         if (obj == null)
    44             return false;
    45         if (getClass() != obj.getClass())
    46             return false;
    47         Person other = (Person) obj;
    48         if (age != other.age)
    49             return false;
    50         if (name == null) {
    51             if (other.name != null)
    52                 return false;
    53         } else if (!name.equals(other.name))
    54             return false;
    55         return true;
    56     }
    57     @Override
    58     public int compareTo(Object o) {
    59         Person person = (Person)o;
    60         if(this.age>person.age) {
    61             return -1;
    62         }else {
    63             return 1;
    64         }
    65         
    66     }
    67     
    68     
    69 }
    View Code

    七、Properties

      Properties类是Hashtable的子类,该对象用于处理属性文件

    •   由于属性文件里的key、value都是字符串类型,所以Properties中里的key和value都是字符串类型
    •   存取数据时,建议使用 setProperty(String key,String value)和 getProperty(String key)

      测试代码:

     1 //Properties用来处理配置文件,key和value都是字符串类型
     2     @Test
     3     public void test4() throws Exception {
     4         Properties prop = new Properties();
     5         FileInputStream fis = new FileInputStream(new File("testproperties.properties"));//文件:testproperties.properties
     6         prop.load(fis);//加载对应流文件
     7         String name = prop.getProperty("name");
     8         String value = prop.getProperty("password");
     9         System.out.println("name:"+name);
    10         System.out.println("value:"+value);
    11     }
    1 name=tom
    2 password=123456
    View Code
    我从来不相信什么懒洋洋的自由。我向往的自由是通过勤奋和努力实现的更广阔的人生。 我要做一个自由又自律的人,靠势必实现的决心认真地活着。
  • 相关阅读:
    阻止页面右键事件
    拖拽效果
    关于事件捕获
    放大镜效果
    如何不用border-radius 写圆角边框
    力扣—— Swap Nodes in Pairs(两两交换链表中的节点) python实现
    力扣—Remove Nth Node From End of List(删除链表的倒数第N个节点) python实现
    力扣 ——Remove Duplicates from Sorted List II(删除排序链表中的重复元素 II)python实现
    力扣 — Rotate List()
    力扣—Remove Duplicates from Sorted List(删除排序链表中的重复元素)python实现
  • 原文地址:https://www.cnblogs.com/lixiuming521125/p/14627549.html
Copyright © 2011-2022 走看看