• 05集合02map


    1、map接口常用的方法

    public static void main(String[] args) {
        /*
        * java.util.Map接口中常用的方法
        * 1、Map和Collection没有继承关系
        * 2、Map以key和value的方式存储数据:键值对
        *   key和value都是引用数据类型
        *   key和value都是存储的对象的存储地址
        *   key起到主导地位,value是key的一个附属品
        * 3、Map接口的常用方法
        *   V map(K key,V value)  向map集合中添加键值对
        *   V get(Object key)    通过key获取value
        *   void clear()      清空map集合
        *   Boolean containsKey(Object key)  判断Map中是否包含某个key
        *   contains 底层比较都是equal方法,自定义的类都需要重写equal方法
        *   Boolean containsValue(Object value)  判断Map中是否包含某个value
        *   boolean isEmpty()   判断集合中元素个数是否为0
        *   Set<K>  keySet()    获取Map集合中所有的key
        *   V remove(Object key)  通过指定key删除这个键值对
        *   int  size()   获取集合中键值对的个数
        *   Collection<V> values()   获取集合中所有的value ,返回一个Collection
        *   Set<Map.Entry<K,V>> entrySet() 将集合中的键值对打包返回
        * */
            //创建集合
            Map<Integer,String> map = new HashMap<>();
            //向集合中添加键值对
            map.put(1,"zhangsan");
            map.put(2,"lili");
            map.put(3,"wanghu");
    
            //通过key获取value
            String  value  = map.get(2);
            System.out.println(value);
    
            //获取键值对的数量
            System.out.println("键值对的数量"+map.size());
    
            //删除元素
            map.remove(1);
            System.out.println("键值对的数量"+map.size());
    
            //判断包含元素
            System.out.println("是否包含元素"+map.containsKey(1));
            System.out.println("是否包含值"+map.containsValue("wanghu"));
    
            //获取所有value值
            Collection<String> values = map.values();
            //foreach
            for(String s:values){
                System.out.println(s);
            }
    
            //清空集合
            map.clear();
            System.out.println("键值对的数量"+map.size());
    
            //判断集合是否为空
            System.out.println(map.isEmpty());
    
    
        }

    2、遍历map集合

     /*
        * Map集合的遍历
        * */
            Map<Integer,String> map = new HashMap<>();
    
            //从集合中添加键值对
            map.put(1,"kim");
            map.put(2,"jack");
            map.put(3,"boy");
    
            //第一种:遍历map集合,获取所有的key,所以的key一个set集合
            Set<Integer> keys = map.keySet();
            Iterator<Integer> it = keys.iterator();
            while(it.hasNext()){
                Integer key = it.next();
                String value = map.get(key);
                System.out.println(key + "=" + value);
            }
    
            //foreach也可以
            for(Integer key: keys){
                System.out.println(key + "=" + map.get(key));
            }
            System.out.println("----------------------------------------");
            //第二种:Set<Map.Entry<K,V>> entrySet()
            //以上这个方法把Map集合直接全部转换成Set集合
            //Set集合中元素的类型是:Map.Entry
            Set<Map.Entry<Integer,String>> set = map.entrySet();
            //遍历Set集合,每次取出一个Node
            //迭代器
            Iterator<Map.Entry<Integer,String>> it2 = set.iterator();
            while(it2.hasNext()){
                Map.Entry<Integer,String> node = it2.next();
                Integer key = node.getKey();
                String value = node.getValue();
                System.out.println(key + "=" + value);
            }
            System.out.println("****************************************************");
            //foreach  效率更高,获取key和value都是从集合中取,适合大量数据类型
            for(Map.Entry<Integer,String> node:set){
                System.out.println(node.getKey() + "=" + node.getValue());
            }
        }

    3、哈希表的数据结构

           /*
            *HashMap集合:
            * 1、HashMap集合底层是哈希表/散列表的数据结构
            * 2、哈希表是一个怎么样的数据结构?
            *   哈希表是一个数组和单向链表的结合体
            *   数组:在查询效率方面较高,随机增删方面效率低
            *   单向链表:在随机增删方面效率高,在查询方面效率低
            *   哈希表将以上的两种数据结构融合在一起,充分发挥他们各自的优点
            * 3、HashMap集合底层的源代码
            *   public class HashMap{
        //HashMap底层实际就是一个数组 (一维数组)
        Node<K,V>[] table;
    
        //静态内部类 HashMap.Node
        static class Node<K,V>{
            final int hash; //哈希值(哈希值是key的hashCode()方法的执行结果,Hash值通过算法可以转换为数组的下标
            final K key;  //存储到Map集合中key
            final V value; //存储到Map集合中那个value
            Node<K,V> nextl;  //下一个节点的内存地址
    
        }
    }
    //哈希表/散列表:一维数组,这个数组中每一个元素是一个单向链表(数组和链表的结合体)
            *4、最主要掌握的:
            * map.put(k,v)
            * v = map.get(k)
            * 以上两个方法的实现原理,是必须掌握的
            * 5、HashMap集合的key特点
            *   无序、不可重复
            *   为什么无序?一维不一定挂到哪个单向链表
            *   不可重复怎么保证的?equals方法
            *   如果key重复了,value要覆盖
            *   放在HashSet集合中的元素也需要同时重写HashCode()和equals方法
            *  注意:同一个单向链表上所有节点的hash值是相同的,因为他们的数组下标是相同的
            *       当时同一个链表上的equals方法返回的false,都不相等
            * 6、HashMap使用不当时,无法发挥性能
            *   假设所有的hashCode()方法返回固定某个值,那么会导致底层哈希表变成纯单向链表,这种情况分为:散列分布不均匀
            *   什么是散列分布均匀?
            *   假设有100个元素,10个单向链表,那么每个单向链表上有10个节点,这是最好的,是散列分布均匀的
            *   假设将所有的hashCode()方法返回值设为不一样的值
            *   不行,因为这样的话会导致底层哈希表成为一维数组,没有链表的概念了
            *   散列函数需要重写hashCode()方法
            * 7、重点:放在HashMap集合key部分的元素,以及放在HashSet集合中的元素,需要同时重写hashCode和equals方法
            * 8、HashMap集合的默认初始化容量是16,默认加载因子是0.75
            *   这个默认加载因子是当HashMap集合底层数据的容量达到75%的时候,数组开始扩容
            *   重点:HashMap集合初始化容量必须是2的倍数,这是官方推荐的
            *   这是因为达到散列均匀,为了提高HashMap集合的存取效率,所必须的
            * */

    4、同时重写hashCode和equals方法

     /*
            * 1、
            *  向Map集合中存,以及从Map集合中取,都是先调用key的hashCode方法,再调用equals方法
            *  equals方法有可能调用,也有可能不调用
            *  拿put(k,v)举例,什么时候equals不会调用
            *   k.hashCode()方法返回哈希值
            *   哈希值经过哈希算法转换成数组下标
            *   数组下标位置如果是null,equals方法不会执行
            *  拿get(k,v)举例,什么时候equals不会调用
            *    k.hashCode()方法返回哈希值
            *    哈希值经过哈希算法转换成数组下标
            *    数组下标位置如果是null,equals方法不会执行
            * 2、注意:如果一个类的equals方法重写,那么hashCode方法必须重写
            *   并且equals方法返回如果是true,hashCode()方法返回的值必须一样
            *   equals方法返回的true表示两个对象相同,在同一个单向链表上比较
            *   那么对于同一个单向链表上的节点来说,他们的哈希值都是相同的
            *   所以hashCode()方法的返回值应该相同
            * 3、hashCode方法和equals方法不用研究,直接使用idea工具生成,但是这两个方法需要同时生成
            * 4、终极结论:
            *   放在HashMap集合key,以及放在HashSet集合中的元素,需要同时重写hashCode和equals方法
            * 5、jdk中,如果哈希表单向链表中元素超过8个,单向链表会变成红黑树这种结构,当红黑树的节点数量小于8,又会重新把红黑树变成单向链表
            *    这种方式也是为了提高检索效率,二叉树的检索会再次缩小扫描范围,提高效率
            *    初始容量是16,加载因子是0.75
            *
            * */
           /*
    *HashMap集合:
    * 1HashMap集合底层是哈希表/散列表的数据结构
    * 2、哈希表是一个怎么样的数据结构?
    * 哈希表是一个数组和单向链表的结合体
    * 数组:在查询效率方面较高,随机增删方面效率低
    * 单向链表:在随机增删方面效率高,在查询方面效率低
    * 哈希表将以上的两种数据结构融合在一起,充分发挥他们各自的优点
    * 3HashMap集合底层的源代码
    * public class HashMap{
    //HashMap底层实际就是一个数组 (一维数组)
    Node<K,V>[] table;

    //静态内部类 HashMap.Node
    static class Node<K,V>{
    final int hash; //哈希值(哈希值是keyhashCode()方法的执行结果,Hash值通过算法可以转换为数组的下标
    final K key; //存储到Map集合中key
    final V value; //存储到Map集合中那个value
    Node<K,V> nextl; //下一个节点的内存地址

    }
    }
    //哈希表/散列表:一维数组,这个数组中每一个元素是一个单向链表(数组和链表的结合体)
    *4、最主要掌握的:
    * map.put(k,v)
    * v = map.get(k)
    * 以上两个方法的实现原理,是必须掌握的
    * 5HashMap集合的key特点
    * 无序、不可重复
    * 为什么无序?一维不一定挂到哪个单向链表
    * 不可重复怎么保证的?equals方法
    * 如果key重复了,value要覆盖
    * 放在HashSet集合中的元素也需要同时重写HashCode()equals方法
    * 注意:同一个单向链表上所有节点的hash值是相同的,因为他们的数组下标是相同的
    * 当时同一个链表上的equals方法返回的false,都不相等
    * 6HashMap使用不当时,无法发挥性能
    * 假设所有的hashCode()方法返回固定某个值,那么会导致底层哈希表变成纯单向链表,这种情况分为:散列分布不均匀
    * 什么是散列分布均匀?
    * 假设有100个元素,10个单向链表,那么每个单向链表上有10个节点,这是最好的,是散列分布均匀的
    * 假设将所有的hashCode()方法返回值设为不一样的值
    * 不行,因为这样的话会导致底层哈希表成为一维数组,没有链表的概念了
    * 散列函数需要重写hashCode()方法
    * 7、重点:放在HashMap集合key部分的元素,以及放在HashSet集合中的元素,需要同时重写hashCodeequals方法
    * 8HashMap集合的默认初始化容量是16,默认加载因子是0.75
    * 这个默认加载因子是当HashMap集合底层数据的容量达到75%的时候,数组开始扩容
    * 重点:HashMap集合初始化容量必须是2的倍数,这是官方推荐的
    * 这是因为达到散列均匀,为了提高HashMap集合的存取效率,所必须的
    * */
  • 相关阅读:
    [单链表]链表指针追赶问题
    二叉查找树与平衡二叉树
    二叉树的下一个结点
    fork进程函数总结
    《Effective C++》Item2:尽量以const,enum,inline替换#define
    Hash表的使用
    [数字]整数数字的算法
    算法题:找出整数数组中两个只出现一次的数字
    删除元素的操作
    [Reprinted] 使用Spring Data Redis操作Redis(一) 很全面
  • 原文地址:https://www.cnblogs.com/xiaoming521/p/15840817.html
Copyright © 2020-2023  润新知