集合框架面试题总结-1

  • ArrayList的扩容机制
    以无参构造方法创建ArrayList时,实际上初始化赋值的是一个空数组。当真正对数组进行添加元素操作时,才真正分配容量。即向数组中添加第一个元素时,数组容量扩为10。

      /**
         * Default initial capacity.
         */
        private static final int DEFAULT_CAPACITY = 10;
    
        /**
         * Shared empty array instance used for empty instances.
         */
        private static final Object[] EMPTY_ELEMENTDATA = {};
    

    因为在源代码中,int newCapacity = oldCapacity + (oldCapacity >> 1),所以ArrayList每次扩容之后容量都会变为原来的1.5倍。

      private void grow(int minCapacity) {
            // overflow-conscious code
            int oldCapacity = elementData.length;
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            if (newCapacity - minCapacity < 0)
                newCapacity = minCapacity;
            if (newCapacity - MAX_ARRAY_SIZE > 0)
                newCapacity = hugeCapacity(minCapacity);
            // minCapacity is usually close to size, so this is a win:
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
    

如果minCapacity大于大容量,则新容量为Integer.MAX_VALUE,否则新容量大小为MAX_ARRAY_SIZE,即为Integer.MAX_VALUE - 8。

  private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
  • ArrayList和Vector的区别是什么?为什么要用ArrayList取代Vector?

    • Vector类的索引方法都是同步的。可以有两个线程安全地访问一个Vector对象,但是一个线程访问Vector的话代码要在同步操作上耗费大量时间。
    • ArrayList不是同步的,所以不需要保证线程安全时建议使用ArrayList
  • ArrayList与LinkedList的区别?

    1. 是否保证线程安全:ArrayList和LinkedList都是不同步的,也就是不保证线程安全
    2. 底层数据结构:ArrayList底层使用的是Object数组;LinkedList底层使用的是双向链表数据结构(JDK1.6之前为循环链表,JDK1.7取消了循环。注意双向链表和双向循环链表的区别,下面有介绍到)
    3. 插入和删除是否首元素位置的影响:① ArrayList采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。比如:执行add(E e)方法的时候,ArrayList会默认在指定的元素追加到此列表的末尾,这种情况的时间复杂度就是O(1)。但是如果要在指定位置i插入和删除元素的话(add ( int index, E element))时间复杂度就是O(n-i)。因为在进行上述操作的时候集合中第i和第i个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。② LinkedList采用链表存储,所以对于add(E e)方法的插入,删除元素时间复杂度不受元素位置的影响,近似O(1),如果是要在指定位置i插入和删除元素的话,(add ( int index, E element))时间复杂度近似为O(n),因为需要先移动到指定位置再插入。
    4. 是否支持快速随机访问:LinkedList不支持高效的随机元素访问,而ArrayList支持。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index) 方法)。
    5. 内存空间占用:ArrayList的空间浪费主要体现在 在list列表的结尾会预留一定的容量空间,而LinkedList的容量空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)。
  • HashMap与Hashtable的区别

    1. 线程是否安全:HashMap是非线程安全的,Hashtable是线程安全的;Hashtable内部的方法基本都经过synchronized修饰。(如果一定要保证线程安全的话可以使用ConcurrentHash);
    2. 效率:因为线程安全的问题,HashMap要比Hashtable效率高一点。另外,Hashtable基本被淘汰,不要在代码中使用它;
    3. 对 Null key 和 Null value 的支持:HashMap中,null可以作为键,这样的键只有一个,可以有一个或多个键所对应的值为null。但是在Hashtable中put进的键值只要有一个null,就直接抛出 NullPointerException。
    4. 初始容量大小和每次扩容量大小的不同: ① 创建时如果不指定容量初始值,Hashtable默认的初始大小为11,之后每次扩容,容量变为原来的2n+1。HashMap默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。② 创建时如果给定了容量初始值,那么Hashtable会直接使用你给定的大小,而HashMap会将其扩充为2的幂次方大小。也就是说HashMap总是使用2的幂次方作为哈希表的大小。
    5. 底层数据结构:JDK1.8以后的HashMap在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转换为红黑树,以减少搜索时间。Hashtable没有这样的机制。
  • List、Set、Map三者的区别

    • List(有序、重复):List接口存储一组不唯一(可以有多个元素引用相同的对象),有序的对象
    • Set(无序、不重复):不允许重复的集合。不会有多个元素引用相同的对象。
    • Map(KV键值对集合):使用键值对来存储。Map会维护与Key有关联的值。两个Key可以引用相同的对象。但Key不能重复,典型的Key是String类型,但也可以是任何对象。
  • RandomAccess接口

    public interface RandomAccess {
    }
    

    通过查看源码可以发现实际上RandomAccess接口中什么都没有定义。所以我认为RandomAccess接口只是一个标识,标识实现这个接口的类具有随机访问功能。

    在binarySearch( ) 方法中,它要判断传入的list是否为RandomAccess接口的实现类的实例,如果是,调用indexBinarySearch( )方法,如果不是,则调用iteratorBinarySearch( )方法。

    public static <T>
        int binarySearch(List<? extends Comparable<? super T>> list, T key) {
            if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
                return Collections.indexedBinarySearch(list, key);
            else
                return Collections.iteratorBinarySearch(list, key);
    }
    

    ArrayList实现了RandomAccess接口,而LinkedList没有实现。是什么原因?

    ​ 我认为还是与底层数据结构有关。ArrayList底层是数组,而LinkedList底层是链表。数组天然支持随机访问,时间复杂度为O(1),所以称为快速随机访问。链表需要遍历到特定位置才能访问到特定位置的元素,时间复杂度为O(n),所以不支持快速随机访问。ArrayList实现了RandomAccess接口,就表明了他具有快速随机访问功能。RandomAccess接口只是标识,并不是说ArrayList实现RandomAccess接口才具有快速随机访问功能的!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354