关于java:对线面试官-别再问我Java-List八股文了

本期是【对线面试官】系列文章的第2期,次要是Java List高频面试题目。

回复【面试】获取大彬精心整顿的大厂面试手册,已助力多位小伙伴斩获大厂offer!

面试现场

面试官:你好,我是面试官xxx,请问你是大彬吗?

大彬:面试官,您好,我是大彬

面试官:当初不便面试吗?

大彬:嗯嗯,能够的

面试官:那咱们当初开始面试吧

面试官看你简历上写了相熟汇合相干内容,你理解Java的List吗?

大彬:嗯,List是一个接口,常见的实现类有ArrayList和LinkedList

面试官讲讲这两个实现类的区别?

独白:老八股文了哈哈

大彬:ArrayList的底层数据结构是数组,反对下标拜访,查问数据快。默认初始值大小为10,容量有余时会进行扩容

大彬:而LinkedList的底层数据结构是链表,将元素增加到链表的开端,无需扩容

面试官嗯嗯,刚刚你提到ArrayList的扩容,具体讲讲?

独白:好家伙,就晓得你会问这个,八股文都曾经筹备好了。

大彬:ArrayList扩容源码实现如下:

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  //扩容
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

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);
}

大彬:能够看到,在grow办法外面进行扩容,将数组容量扩充为原来的1.5倍。

大彬:举个例子,如果初始化的值是8,当增加第9个元素的时候,发现数组空间不够,就会进行扩容,扩容之后容量为12。

大彬:扩容之后,会调用Arrays.copyOf()办法对数组进行拷贝。

面试官嗯,不错,那ArrayList和LinkedList别离实用于什么场景?

大彬:对于随机index拜访的get和set办法,ArrayList的速度要优于LinkedList。因为ArrayList间接通过数组下标间接找到元素;LinkedList要挪动指针遍历每个元素直到找到为止。

大彬:新增和删除元素,LinkedList的速度要优于ArrayList。因为ArrayList在新增和删除元素时,可能扩容和复制数组;而LinkedList的新增和删除操作只须要批改指针即可。

大彬:因而,ArrayList实用于查问多,增删少的场景。而LinkedList实用于查问少,增删多的场景

面试官讲讲Set和List的区别?

大彬:List 以索引来存取元素,有序的,元素是容许反复的,能够插入多个null;Set 不能寄存反复元素,无序的,只容许插入一个null。

大彬:List 底层实现有数组、链表两种形式;Set 基于 Map 实现,Set 里的元素值就是 Map的键值。

面试官理解Vector吗?

大彬:嗯,Vector是底层构造是数组,当初根本没有应用Vector了,因为操作Vector效率比拟低。绝对于ArrayList,它是线程平安的,在扩容的时候容量扩大为原来的2倍。

面试官嗯,那你还晓得有哪些线程平安的List吗?

大彬:能够应用Collections.synchronizedList()办法返回一个线程平安的List。

大彬:还有另一种形式,应用CopyOnWriteArrayList。

面试官嗯哼,刚刚你提到CopyOnWriteArrayList,具体讲讲它的原理?

独白:这也太卷了吧,一言不合就是底层原理…

大彬:CopyOnWriteArrayList是一个线程平安的List,底层是通过复制数组的形式来实现的。

大彬:所谓的CopyOnWrite,就是写时复制。

大彬:当咱们往容器增加元素时,不间接往容器增加,而是先将以后容器进行复制,复制出一个新的容器,而后往新的容器增加元素,增加完元素之后,再将原容器的援用指向新容器。

大彬:这样做的益处就是能够对CopyOnWrite容器进行并发的读而不须要加锁,因为以后容器不会被批改。

public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock(); //add办法须要加锁
    try {
        Object[] elements = getArray();
        int len = elements.length;
        Object[] newElements = Arrays.copyOf(elements, len + 1); //复制新数组
        newElements[len] = e;
        setArray(newElements); //原容器的援用指向新容器
        return true;
    } finally {
        lock.unlock();
    }
}

面试官那你能说说CopyOnWriteArrayList有什么毛病吗?

大彬:次要有以下两个问题。

大彬:内存占用问题。因为CopyOnWrite的写时复制机制,在进行写操作的时候,内存里会同时驻扎两个对象的内存。

大彬:CopyOnWrite容器不能保证数据的实时一致性,可能读取到旧数据。

面试官:嗯,能够。

面试官问一些平时开发常常遇到的问题,怎么给List排序呢?

大彬:能够应用list本身的sort办法,或者应用Collections.sort(list)办法。

面试官怎么在遍历 ArrayList 时移除一个元素?

大彬:如果应用foreach删除元素的话,会导致疾速失败(fast-fail)问题,能够应用迭代器的 remove() 办法,防止fast-fail问题。

Iterator itr = list.iterator();
while(itr.hasNext()) {
      if(itr.next().equals("dabin") {
        itr.remove();
      }
}

面试官:根底还不错!回去等告诉

大彬:好的,谢谢你

独白:回去等告诉?不会凉了吧…

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据