美团外卖配送部后台开发面经---牛客网

一、hashMap和ConcurrentHashMap的区别数组

     答:hashMap是无序键不可重复值能够重复;线程不安全的;可存一个null键和多个null值,“数组加链表”结构,数组长度默认16;经过key的hashCode值去决定该键值对存      在数组哪一个空间上即hashCode%lenth=index,此处length通常默认16,若是该位置上已经有其余的;若要使其线程安全,则可以使用Collections类的方法:Map<String,String> map = Collections.synchronizedMap(new HashMap());安全

        ConcurrentHashMap:是在hashMap的基础上,把数据分红许多的segment(默认16个)每次操做时会对该segment(一个存放Entry的桶,默认实现ReentrantLock)加锁,避免多线程锁的概率,提升并发效率多线程

  补充:并发

    问题¥:hashMap中key为null的值存在哪里?高并发

            for循环会默认在table[0]中查找key为null的值,如果找到了,就把这个新value值赋给这个元素的value,并返回原来的那个value,若没找到,就把该键值对存到table[0]链表的表头。spa

          

 

 

   问题¥¥:ConcurrentHashMap详解:线程

        ConcurrentHashMap是线程安全的(基于lock实现的,同步的时候锁住的不是整个对象,而加了synchronized的是锁住了整个的对象),实现了Map接口,他是在hashMap的基础上,将数指针

      据分为不少个小的segment(桶,他继承了ReentrantLock),默认16,每次操做都对segment加锁,避免多线程的概率,提升并发效率,从他的源码中能够看出,他引入了一个“分段锁”的概code

      念,就是能够看做把一个Map分红不少个HashTable(hashTable每次是对一整张表加锁),根据key.hashCode()来决定把key放到哪一个hashTable中,get时根据计算出来的key.hashCode(),从哪对象

      个hashTable中拿出

      装载因子:0.75,若是表中75%的位置已经填入元素,就会扩容两倍(例如:默认初始容量为16,当已用空间为12(75%)时,会自动扩容为2*16=32)

      装载因子就是hash表中已占空间和所有空间的比值,默认0.75

        初始容量默认为16

      装载因子越大,空间利用率越高,可是冲突机会加大,增大查询数据的开销,查询速度慢,反而空间利用率低,冲突机会减少

二、hashMap内部具体如何实现的

          hashMap实现了map接口,无序不重复,可存一个null键和多个null值,线程不安全,,底层是“数组加链表“结构,默认初始容量是16,加载因子是0.75,当调用put方法存储键值对时,会先调用key的 

      hashCode方法计算hashCode值,经过hashCode%length=index来决定把Entry存在数组的下标,此时如果该下标已经存在entry了,则调用key的equals方法,再去比较,若此时不相同则把新添加进来的entry

   存在链表头部,以前的entry日后移,此时如果用equals比较相同表示重复则用新的value去替换旧的value

三、若是hashMap的key是一个自定义的类,怎么办

       重写equals方法和hashCode方法,若是不用对象的话就用的是那些已经默认重写过equals和hashCode的String或者其余的一些引用对象,如Date,因此若是是本身定义的类时就要重写equals和hashCode方法,由于hashCode方法构造的hashCode值是默认的内存地址,这样即使有相同含义的两个对象,比较也是不相等的,例如:

          User u1 = new User (“hello”,”ren”);

          User u2 = new User (“hello”,”ren”);

  正常理解这两个对象加入HashMap应该是同样的,只添加一个,添加的第二个的value把第一个的覆盖掉,可是若是不重写的话比较是其地址,不相等,添加的是两个。

  补充:

        问题¥:equals和==的区别:

       1)对于==:用于基本数据类型比较的是数值大小是否相等,对于非基本数据类型(引用类型)比较其地址是否一致

    2)对于equals:不能用于比较基本数据类型,只能用于比较引用类型,没有重写equals方法时,直接比较的是两个对象的地址,如果重写了equals方法,如

  String、Date等比较的是所指向对象的内容

四、为何重写equals还要重写hashcode?

  hashCode没有重写时用地址构造hashCode值,地址不一样值不一样,此时如果有两个对象,u.equals(u1)只能说明内容相同(此时已经重写了equals方法),调用map.put()方法,hashCode值不一样,就会把u和u1分别放入两个桶中,可是这时候把map中的内容打印出来就会发现:

    1、这时候就会形成重复

       

 

        2、再者hashCode就是肯定entry存在哪一个桶中的,此时如果只知道两个两个键equals方法为true,可是不知道是否在一个桶,这样的比较毫无心义

       

 

     通俗来说:想一想,你要在一个桶里找东西,你必须先要找到这个桶啊,你不经过重写hashcode()来找到桶,光重写equals()有什么用啊

  重写后的hashCode方法中经过String类型参数去调用了String类的hashCode方法,此时如果参数相同则值相同,参数不一样值不一样,如若此处name,title参数是其余引用类型,则在其余类型中也要重写hashCode和equals方法

  

五、ArrayList和LinkedList的区别,若是一直在list的尾部添加元素,用哪一个效率高?

  (1)ArrayList:底层是数组实现,有下标空间连续因此查询快,随机读取效率很高,增删慢,存储的是对象的引用而不是对象自己,可是线程不安全,替代了vector

      LinkedList:底层是基于链表实现的,有指针因此增删快(好比新来一个节点只须要把上一个节点告诉他(上个节点的指针有指向)便可),但空间不连续查询很慢,须要遍历整个链表,不具备随机访问性

    (2)效率:

      list开始LinkedList>ArrayList

      list中间LinkedList=ArrayList

      list最后LinkedList<ArrayList

      list随机插入LinkedList>ArrayList

相关文章
相关标签/搜索