• 双列集合Map相关面试题


    一、了解Map集合吗?Map集合都有哪些实现

    • HashMap
    • HashTable
    • LinkedHashMap
    • TreeMap
    • ConcurrentHashMap

    二、HashMap和HashTable之间的区别

    1、定义

      HashMap底层基于数组+单向链表(红黑树)非线程安全允许有空的键和值  

      • 数组:Node<K,V> [] table ,每一个元素都是一个Node
      • 单向链表:Node<K,V> next,当发生Hash碰撞,会追加链表,当链表长度大于8,那就转换为红黑树

      HashTable底层基于哈希表实现线程是安全不允许有空的键和值

    2、继承

      HashMap继承自AbstractMap

      HashTable是继承自Dictionary

    3、扩容原理

      HashMap的初始容量为16,之后每次扩容,容量就变成了原来的2倍

      HashTable的初始容量为11,之后每次扩容,容量就变成了原来的2n+1

    三、hashCode()和equals()方法使用场景

    hashCode():

      顶级父类Object当中的方法,返回值类型为int类型的值,根据一定的规则(存储地址,字段,长度等等)生成一个数组,数据保存的就是Hash值
    equals():

      顶级类Object中的方法,根据一定的比较规则,判断对象是否一致,底层一般逻辑

        1.判断两个对象的内存地址是否一样
        2.非空判断和Class类型判断
        3.强转
        4.对象中的字段一一匹配

    package com.zn.mytest;
    
    import java.util.Objects;
    
    public class UserTest {
        private int uid;
        private String uName;
    
        public int getUid() {
            return uid;
        }
    
        public void setUid(int uid) {
            this.uid = uid;
        }
    
        public String getuName() {
            return uName;
        }
    
        public void setuName(String uName) {
            this.uName = uName;
        }
    
        @Override
        public boolean equals(Object o) {
            //判断两个对象内存地址是否一样
            if (this == o) return true;
            //非空判断和class判断
            if (o == null || getClass() != o.getClass()) return false;
            //强转
            UserTest userTest = (UserTest) o;
            //对象中的字段--匹配
            return uid == userTest.uid &&
                    Objects.equals(uName, userTest.uName);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(uid, uName);
        }
    }

    四、HashMap和TreeMap应该如何选择

    HashMap:

      底层采用数组+链表(红黑树)结构,可以实现快速的存储和检索,但是数据是无序的,适用于在Map当中插入删除或者获取元素
    TreeMap:

      存储结构是一个平衡二叉树,具体实现方式为红黑树,默认采用自然排序,可以自定义排序规则,但是需要实现Comparator接口能够便捷的实现内部元素的各种排序,但是性能比HashMap差,适用于按照自然排序和自定义排序规则

    五、Set和Map的关系

      Set核心就是保存不重复的元素,存储一组唯一的对象
      set当中每一种实现都对应Map
      HashSet对应的HashMap,TreeSet对应的TreeMap

      HashSet对应的底层就是new HashMap,TreeSet对应的底层就是new TreeMap;

    HashSet:

      

    TreeSet:

       

    六、常见的Map排序规则

      按照添加规则使用LinkedHashMap,按照自然排序或者自定义规则排序可以采用TreeMap

    1、TreeMap排序  

        TreeMap只能根据key进行排序,TreeMap本身是个二叉树,元素的顺序是由key的值决定的;

        按照自然排序可以采用TreeMap;

    实现代码:

    package com.zn.mytest;
    
    import java.util.TreeMap;
    
    public class TreeMapTest {
        public static void main(String[] args) {
            TreeMap<String, String> map = new TreeMap<String,String>();
            map.put("1","A");
            map.put("2","B");
            map.put("3","C");
            map.put("4","D");
            map.put("5","E");
            System.out.println(map);
        }
    }

    效果展示:

      

    2、HashMap排序

        HashMap本身是没有顺序的,不能直接对其进行排序;

       要排序,只能先转成list;

    实现代码:

    package com.zn.mytest;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Map;
    
    public class HashMapTest {
        public static void main(String[] args) {
            HashMap<Integer,String> map = new HashMap<Integer,String>();
            map.put(1,"A");
            map.put(3,"B");
            map.put(2,"C");
            map.put(4,"D");
            map.put(5,"E");
            ArrayList<Object> list = new ArrayList<>();
            for (Map.Entry<Integer,String> entry:map.entrySet()){
                System.out.println("entry.getKey.hash:"+entry.getKey().hashCode());
                list.add(entry.getValue());
            }
            System.out.println(list);
        }
    }

    效果展示:

      

    3、LinkedHashMap排序

        插入顺序,遍历LinkedHashMap时,先得到的记录肯定是先插入的;

    实现代码:

    package com.zn.mytest;
    
    import java.util.LinkedHashMap;
    
    public class LinkedListTest {
        public static void main(String[] args) {
            LinkedHashMap<String, String> map = new LinkedHashMap<>();
            for (int i=0;i<10;i++){
                map.put("key"+i,"value"+i);
            }
            map.get("key"+3);
            for (String value:map.keySet()){
                System.out.println(value);
            }
        }
    }

    效果展示:

      

    七、如何保证Map线程安全

      多线程环境下,可以使用concurrent包下有一个ConcurrentHashMap或者是使用Collections.synchronizedList(new HashMap<K,V>());

      ConcurrentHashMap保证线程安全,效率比HashTable高,采分段锁

  • 相关阅读:
    关于android studio几种常见的错误解决
    Codeforces 528A Glass Carving STL模拟
    Windows 8 快捷键收集整理
    设计模式学习05—原型模式
    Connect the Campus (Uva 10397 Prim || Kruskal + 并查集)
    WordPress改动新用户注冊邮件内容--自己定义插件
    servlet_1
    我使用过的Linux命令之file
    灵活使用getconf命令来获取系统信息
    odd number、 even number
  • 原文地址:https://www.cnblogs.com/Zzzzn/p/12504248.html
Copyright © 2020-2023  润新知