• 重学java基础----集合框架(2)


    参考于韩顺平老师JAVA基础课程以及笔记

    本文讲解双列集合

    在这里插入图片描述

    Map接口以及常用方法

    1. JDK1.8 接口的特点
      在这里插入图片描述
      在这里插入图片描述

    2. Map接口常用方法
      在这里插入图片描述在这里插入图片描述 在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述在这里插入图片描述

    3. Map接口遍历方法
      在这里插入图片描述

    使用KeySet(),取出所有的key,通过key取出对应的value
    主要两种方法:增强for循环迭代器

       //增强for循环
            for (Object key : set) {
                System.out.println(map.get(key));
            }
    
       //迭代器
            System.out.println("===========");
            Iterator iterator = set.iterator();
            while (iterator.hasNext()) {
                Object key = iterator.next();
                System.out.println(map.get(key));
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    使用values()获取所有的值
    主要有:增强for循环迭代器

         Collection values = map.values();
            //可以使用所有的collection遍历的方法
    
            //(1)增强for
            for (Object value : values) {
                System.out.println(value);
            }
            //(2)迭代器
            while (iterator.hasNext()) {
                Object next = iterator.next();
                System.out.println(next);
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    通过EntrySet来获取k-v
    主要有:增强for循环迭代器

     Set entrySet = map.entrySet();// EntrySet>
    
    //(1)增强for
    System.out.println("--------------");
    for (Object entry : entrySet) {
       //将entry转成Map.Entry
        Map.Entry m =(Map.Entry)entry;
        System.out.println(m.getKey()+"-"+m.getValue());
    }
    //(2)迭代器
    System.out.println("------------");
    Iterator it = entrySet.iterator();
    while (it.hasNext()) {
        Object entry =  it.next();
    
        //向下转型
        Map.Entry m=(Map.Entry)entry;
        System.out.println(m.getKey()+"-"+m.getValue());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    Map接口实现类–HashMap

    • 特点
      在这里插入图片描述

    • HashMap底层机制与源码剖析(重要)
      在这里插入图片描述
      在这里插入图片描述

    • 测试代码

     package com.map;
    
    import java.util.HashMap;
    import java.util.HashSet;
    
    /**
     * @Description
     * @autor wzl
     * @date 2022/8/13-21:48
     */
    public class HashMapSource {
        public static void main(String[] args) {
            HashMap map =new HashMap();
            map.put("java",10);
            map.put("php",10);
            map.put("java",20);
    
            System.out.println("map="+map);
        }
        /*
     * 执行构造器 new HashMap()
    初始化加载因子 loadfactor = 0.75
    HashMap$Node[] table = null
     * 执行 put 调用 hash 方法,计算 key 的 hash 值 (h = key.hashCode()) ^ (h >>> 16)
    public V put(K key, V value) {//K = "java" value = 10
    return putVal(hash(key), key, value, false, true);
    }
     * 执行 putVal
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
    boolean evict) {
    Node[] tab; Node p; int n, i;//辅助变量
    //如果底层的 table 数组为 null, 或者 length =0 , 就扩容到 16
    if ((tab = table) == null || (n = tab.length) == 0)
    n = (tab = resize()).length;
    //取出 hash 值对应的 table 的索引位置的 Node, 如果为 null, 就直接把加入的 k-v
    //, 创建成一个 Node ,加入该位置即可
    if ((p = tab[i = (n - 1) & hash]) == null)
    tab[i] = newNode(hash, key, value, null);
    else {
    Node e; K k;//辅助变量
    // 如果 table 的索引位置的 key 的 hash 相同和新的 key 的 hash 值相同,
    // 并 满足(table 现有的结点的 key 和准备添加的 key 是同一个对象 || equals 返回真)
    // 就认为不能加入新的 k-v
    if (p.hash == hash &&
    ((k = p.key) == key || (key != null && key.equals(k))))
    e = p;
    else if (p instanceof TreeNode)//如果当前的 table 的已有的 Node 是红黑树,就按照红黑树的方式处
    理
    e = ((TreeNode)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);
    //加入后,判断当前链表的个数,是否已经到 8 个,到 8 个,后
    //就调用 treeifyBin 方法进行红黑树的转换
    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
    treeifyBin(tab, hash);
    break;
    }
    if (e.hash == hash && //如果在循环比较过程中,发现有相同,就 break,就只是替换 value
    ((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; //替换,key 对应 value
    afterNodeAccess(e);
    return oldValue;
    }
    }
    ++modCount;//每增加一个 Node ,就 size++
    if (++size > threshold[12-24-48])//如 size > 临界值,就扩容
    resize();
    afterNodeInsertion(evict);
    return null;
    }
     * 关于树化(转成红黑树)
    //如果 table 为 null ,或者大小还没有到 64,暂时不树化,而是进行扩容.
    //否则才会真正的树化 -> 剪枝
    final void treeifyBin(Node[] tab, int hash) {
    int n, index; Node e;
    if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
    resize();
    }
    */
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • HashMap扩容机制(与HashSet部分一样)
    public class HashMapSource2 {
       public static void main(String[] args) {
       HashMap hashMap = new HashMap();
       for(int i = 1; i <= 12; i++) {
       hashMap.put(i, "hello");
    }
    hashMap.put("aaa", "bbb");
    System.out.println("hashMap=" + hashMap);//12 个 k-v
    }
    }
    class A {
    private int num;
    publicA(int num) {
    this.num = num;
    }
    //所有的 A 对象的 hashCode 都是 100
    // @Override
    // public int hashCode() {
    // return 100;
    // }
    @Override
    public String toString() {
    return "\nA{" +
    "num=" + num +
    '}';
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    Map接口实现类-HashTable

    • 特点
      在这里插入图片描述

    • 底层源码与扩容机制

    1.底层有数组,Hashtable$Entry[],初始化大小为11
    2.临界值 threshold 8=11*0.75
    3.扩容:按照自己的扩容机制进行
    4.执行方法 addEntry(hash,key,value,index);添加k-v封装到Entry
    5.当if(count>=threshold)满足时,就进行扩容
    6.按照2n+1扩容

    package com.map;
    
    import javax.swing.table.TableCellEditor;
    import java.lang.annotation.Target;
    import java.util.Hashtable;
    
    /**
     * @Description
     * @autor wzl
     * @date 2022/8/14-7:50
     */
    public class HashTableSoure {
        public static void main(String[] args) {
            Hashtable hashtable =new Hashtable();
            hashtable.put("lucy",100);
            hashtable.put("jack",200);
            hashtable.put("jac",200);
            hashtable.put("ja",200);
            hashtable.put("j",200);
            hashtable.put("ack",200);
            hashtable.put("ck",200);
            hashtable.put("k",200);
            hashtable.put("jackk",200);
    
            System.out.println(hashtable);
    
            //HashTable底层原理
            /*
            1.底层有数组,Hashtable$Entry[],初始化大小为11
            2.临界值 threshold 8=11*0.75
            3.扩容:按照自己的扩容机制进行
            4.执行方法 addEntry(hash,key,value,index);添加k-v封装到Entry
            5.当if(count>=threshold)满足时,就进行扩容
            6.按照2n+1扩容
             */
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    在这里插入图片描述

    HashMap VS HashTable

    在这里插入图片描述

    Map接口实现类-Properties

    • 特点

    由于继承Hashtable类,所以特性与它一样,底层扩容机制也一样

    在这里插入图片描述

    • 基本使用
     package com.map;
    
    import java.util.Properties;
    
    /**
     * @Description
     * @autor wzl
     * @date 2022/8/14-8:16
     */
    public class Properties_ {
        public static void main(String[] args) {
            Properties properties =new Properties();
            properties.put("lucy",100);
            properties.put("john",100);
            properties.put("lic",100);
            System.out.println(properties);
    
            //如何通过key获取对应值 查
            System.out.println(properties.getProperty("lic"));
            System.out.println(properties.get("lic"));
    
            //删除
            properties.remove("lucy");
            System.out.println(properties);
    
            //改
            properties.put("john",200);
            System.out.println(properties);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    TreeSet源码解读

    1. 当我们使用无参构造器创建TreeSet时,它仍然是无序的
    2. 假设按照字符串大小来排序
    3. 使用TreeSet提供给的一个构造器,可以传入一个比较器(匿名内部类)
    package com.map;
    
    import javax.transaction.TransactionRequiredException;
    import java.util.Comparator;
    import java.util.TreeSet;
    
    /**
     * @Description
     * @autor wzl
     * @date 2022/8/14-8:25
     */
    public class TreeSet_ {
        public static void main(String[] args) {
    
            /*
            1. 当我们使用无参构造器创建TreeSet时,它仍然是无序的
            2. 假设按照字符串大小来排序
            3. 使用TreeSet提供给的一个构造器,可以传入一个比较器(匿名内部类)
    
             */
            //TreeSet treeSet=new TreeSet();
    
            TreeSet treeSet = new TreeSet(new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    //下面 调用String的compareTo方法进行字符串大小比较
    
    
                    return ((String) o1).compareTo((String) o2);
                }
            });
            treeSet.add("john");
            treeSet.add("lucy");
            treeSet.add("lick");
            treeSet.add("a");
    
            System.out.println(treeSet);
    
            /*
               1. 构造器把传入的比较器对象,赋给了 TreeSet 的底层的 TreeMap 的属性 this.comparator
               public TreeMap(Comparator comparator) {
               this.comparator = comparator;
                 }
               2. 在 调用 treeSet.add("tom"), 在底层会执行到
               if (cpr != null) {//cpr 就是我们的匿名内部类(对象)
                }do {
                parent = t;
               //动态绑定到我们的匿名内部类(对象)compare
              cmp = cpr.compare(key, t.key);
                if (cmp < 0)
                t = t.left;
                else if (cmp > 0)
                t = t.right;
                else //如果相等,即返回 0,这个 Key 就没有加入
                return t.setValue(value);
                } while (t != null);
            }
    */
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    在这里插入图片描述

    TreeMap源码解读

    package com.map;
    
    import java.util.Comparator;
    import java.util.TreeMap;
    
    /**
     * @Description
     * @autor wzl
     * @date 2022/8/14-8:54
     */
    public class TreeMap_ {
        public static void main(String[] args) {
    
            //使用默认的构造器,创建TreeMap,输入和输出顺序是不一致的(也没有排序)
            //TreeMap treeMap=new TreeMap();
            TreeMap treeMap=new TreeMap(new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    return ((String)o1).length()-((String)o2).length();
                   // return ((String)o1).compareTo((String)o2);
                }
            });
            treeMap.put("jack", "杰克");
            treeMap.put("tom", "汤姆");
            treeMap.put("kristina", "克瑞斯提诺");
            treeMap.put("smith", "斯密斯");
            treeMap.put("hsp", "韩顺平");//加入不了
            System.out.println("treemap=" + treeMap);
    
            /*
            1. 构造器. 把传入的实现了 Comparator 接口的匿名内部类(对象),传给给 				               TreeMap 的 comparator
            public TreeMap(Comparator comparator) {
             this.comparator = comparator;
    }
     * 调用 put 方法
    2.1 第一次添加, 把 k-v 封装到 Entry 对象,放入 root
           Entry t = root;
       		if (t == null) {
    		compare(key, key); // type (and possibly null) check
    		root = new Entry<>(key, value, null);
    		size = 1;
    		modCount++;
    		return null;
    		}
    2.2 以后添加
    		Comparator cpr = comparator;
    		if (cpr != null) {
    		do { //遍历所有的 key , 给当前 key 找到适当位置
    		parent = t;
    		cmp = cpr.compare(key, t.key);//动态绑定到我们的匿名内部类的 compare
    		if (cmp < 0)
    		t = t.left;
    		else if (cmp > 0)
    		t = t.right;
    		else //如果遍历过程中,发现准备添加 Key 和当前已有的 Key 相等,就不添加
    		return t.setValue(value);
    		} while (t != null);
    }
             */
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    如何选择集合类

    在这里插入图片描述

    Collections工具类

    • 作用
      在这里插入图片描述

    • 常用方法举例
      在这里插入图片描述
      在这里插入图片描述

    集合练习题

    在这里插入图片描述
    在这里插入图片描述

    关键看Person()类是否实现了compareable接口,如果没有,会出现类型转换异常
    在这里插入图片描述

  • 相关阅读:
    多级缓存之缓存同步
    牛客—链表中倒数第k个结点
    隆云通空气温湿,光照三合一传感器
    基于ssm的高校校友信息管理系统设计与实现-计算机毕业设计
    访问链表中的某个元素(快慢指针)
    考 PMP 证书真有用吗?
    小马识途:如何稀释百科词条里的负面信息?
    Fast-DDS 服务发现简要概述
    mysql数据的备份和恢复
    已知中序遍历数组和先序遍历数组,返回后序遗历数组
  • 原文地址:https://blog.csdn.net/qq_38716929/article/details/126268414