Map集合大总结

若想了解底层请参考底层剖析的网址

一、Map
    Map集合的特点:
        将键映射到值的对象,一个映射不能包含重复的键,每个键只能映射一个值
        
    Map集合的数据结构针对键有效,跟值无关
    Collection集合的数据结构针对元素有效
    
    Map和Collection的区别
    Map存储的是键值对形式的元素,键唯一,只可以重复
    Collection存储的是单独出现的元素,子接口Set元素唯一,子接口List元素可重复。
    
    Map集合的遍历
    a:键找值  (map.keySet())
    b:键值对对象找键和值 (map.entrySet())
    
二、HashMap集合的练习
    特点:无序、唯一
    底层数据结构是哈希表:(数组加单链表)


    利用hashCode()和equals()方法保证键的唯一性
    利用头插法来加入hash值一样的Map.Entry实体
    底层剖析 
    https://blog.csdn.net/wufaliang003/article/details/79997585
    https://blog.csdn.net/P_Doraemon/article/details/80353579
    
三、LinkedHashMap集合
    特点:有序、唯一
    底层数据结构是哈希表(数组加单链表)+双向循环链表

 


    使用尾插法来加入hash值一样的Entry实体
    recordAccess()决定2种顺序 -- 看源码put
        a:按访问进行排序 -- LRU算法  将旧的相同的键的Entry实体删除将get或者put访问的Entry实体添加到双向循环链表尾部(LRU算法)

package day22;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

public class Test {
	
	public static void main(String[] args) {
		LinkedHashMap linkedHashMap =new  LinkedHashMap(16, 1.2f, true); 
		linkedHashMap.put("111", "111");

		 linkedHashMap.put("222", "222");

		 linkedHashMap.put("333", "333");

		 linkedHashMap.put("444", "444");
		 loopLinkedHashMap(linkedHashMap);

		 linkedHashMap.get("111");

		 loopLinkedHashMap(linkedHashMap);

		 linkedHashMap.put("222", "2222");

		 loopLinkedHashMap(linkedHashMap);

		}

		  

		public static void loopLinkedHashMap(LinkedHashMap<String, String> linkedHashMap)

		{

		 Set<Map.Entry<String, String>> set = linkedHashMap.entrySet();

		 Iterator<Map.Entry<String, String>> iterator = set.iterator();

		  

		 while (iterator.hasNext())

		 {

		  System.out.print(iterator.next() + " ");

		 }

		 System.out.println();

		}
	
}



结果显示

111=111 222=222 333=333 444=444 
222=222 333=333 444=444 111=111 
333=333 444=444 111=111 222=2222 


        b:按照插入顺序排序 -- 就是将相同的键的Entry实体替换或者若双向循环链表中没有相同的键的Entry,则将新的Entry实体添加到尾部(FIFO)

package day22;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

public class Test {
	
	public static void main(String[] args) {
		LinkedHashMap linkedHashMap =new  LinkedHashMap(16, 1.2f, false); 
		linkedHashMap.put("111", "111");

		 linkedHashMap.put("222", "222");

		 linkedHashMap.put("333", "333");

		 linkedHashMap.put("444", "444");
		 loopLinkedHashMap(linkedHashMap);

		 linkedHashMap.get("111");

		 loopLinkedHashMap(linkedHashMap);

		 linkedHashMap.put("222", "2222");

		 loopLinkedHashMap(linkedHashMap);

		}

		  

		public static void loopLinkedHashMap(LinkedHashMap<String, String> linkedHashMap)

		{

		 Set<Map.Entry<String, String>> set = linkedHashMap.entrySet();

		 Iterator<Map.Entry<String, String>> iterator = set.iterator();

		  

		 while (iterator.hasNext())

		 {

		  System.out.print(iterator.next() + " ");

		 }

		 System.out.println();

		}
	
}




        结果显示

111=111 222=222 333=333 444=444 
111=111 222=222 333=333 444=444 
111=111 222=2222 333=333 444=444 


    注意a和b的区别在于
    

 public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }
       void recordAccess(HashMap<K,V> m) {
            LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
            if (lm.accessOrder) {
                lm.modCount++;
                remove();
                addBefore(lm.header);
            }
        }
        
         // 将原来相同键且值换了的Entry实体删除
        private void remove() {
            before.after = after;
            after.before = before;
        }

        //在双向循环链表末尾添加相同键且值换了的Entry实体
        private void addBefore(Entry<K,V> existingEntry) {
            after  = existingEntry;
            before = existingEntry.before;
            before.after = this;
            after.before = this;
        }


        
    当Map的键相同时
        若使用a方法lm.accessOrder == true 
        则会将原来相同键且值换了的Entry实体(也就是说将要删除的Entry和插入的Entry键值对相同)删除
        在双向循环链表末尾添加和删除的Entry键值对一样的Entry实体
        若使用b方法lm.accessOrder == false
        直接在键相同的 Entry实体上替换原来的值
        
        底层剖析 
        http://www.php.cn/java-article-362041.html  (LinkedHashMap的访问顺序)
        https://blog.csdn.net/alexdedream/article/details/84955245   (LinkedHashMap的存储顺序)
        https://www.cnblogs.com/whgk/p/6169622.html
四、TreeMap集合
    特点:排序、唯一
    底层数据结构是红黑树(二叉排序树算法)
    两种排序方式(看构造方法) 
        a:自然排序(comparable接口 -- compareto)
        b:比较器排序(comparator -- compare ) -- 推荐用内部类
        
五、HashMap和Hashtable的区别
    Hashtable:线程安全,效率低
    不允许NULL值或者NULL键
    HashMap:线程不安全,效率高
    允许NULL值或者NULL键

六、Collections
        (1)含义:针对集合进行操作的工具类
        (2)面试题:Collection和Collections的区别
        A:Collection 是单列集合的顶层接口,有两个子接口List和Set
        B:Collections 是针对集合进行操作的工具类,可以对集合进行排序和查找等
        (3)常见的几个小方法:
        A:public static <T> void sort(List<T> list)
        B:public static <T> int binarySearch(List<?> list,T key)
        C:public static <T> T max(Collection<?> coll)
        D:public static void reverse(List<?> list)
        E:public static void shuffle(List<?> list)
            
    
    
    
    
    
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值