大厂ArrayList的面试题:
1.new ArrayList的时候底层new了什么?
2.凡数组都有类型,什么类型?
3.数组要在内存中占据连续的内存空间,初始值以java8为例是多少?
4.存25个元素进去可以吗?底层发生什么?底层扩容到多少?
5.搬家的过程用到了什么方法?
6.第二次扩容扩到多少?
7.Array线程安全还是不安全?
8.请写一个线程不安全的例子?
答案:
1.object类型的数组
2.object类型
3.10
4.可以的,底层会发生扩容,扩容到原值一半,15
5.Arrays.copyOf()
Arrays的copyOf()方法
具体的参考:https://blog.csdn.net/qq_25131363/article/details/85001414
6.22 扩容到原值的一半取整。可以debug打断点看到。
7.线程不安全
8.
/*
* 1.故障现象
* 并发异常
* java.util.ConcurrentModificationException
* 2.导致原因
* 多线程并发争抢同一个类
* 3.解决方案
* 3.1 new Vector<>
* 3.2 Collections.synchronizedlist(new ArrayList<>());
* 3.3 CopyOnWriteArrayList();
*
* 4.优化建设(同样的错误不犯第二次)
* 高并发的情况下使用JUC包下的工具来解决
*
*/
public class NotSafeDemo03 {
public static void main(String[] args) {
//写时复制类
List list = new CopyOnWriteArrayList();//Collections.synchronizedList(new ArrayList<>());//new Vector<>();//ArrayList<>();
for (int i = 1; i <=30 ; i++)
{
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
因此一般有2种解决办法:
1)在使用iterator迭代的时候使用synchronized或者Lock进行同步;
2)使用并发容器CopyOnWriteArrayList代替ArrayList和Vector。
关于并发容器的内容将在下一篇文章中讲述。
参考资料:
9.vector线程安全,ArrayList线程不安全,为什么?
如果强调效率就选ArrayList
10.collection和collectionsu有什么区别
collections:集合接口的工具类
collection:接口
笔记:写时复制
copyonwrite容器即写时复制的容器,往一个容器添加元素的时候,不直接往当前容器的objectp[]添加,而是先将当前的容器object[]进行copy,复制出一个新的容器object[] new Elements,然后新的容器object[] new Elements添加元素,添加完元素后,再将原容器的引用指向新的容器,setArray(new Elements);这样做的好处是可以针对copyonwrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素,所以copyonwrite是一种读写分离的思想,读和写不同的容器。
public boolean add(E e) {
final ReentrantLock lock = this.lock;
// 上锁
lock.lock();
try {
// 获取对象数组
Object[] elements = getArray(); // =========== 旧对象数组
int len = elements.length;
// 复制原来的对象数组,并返回一个比源对象数组长度 +1 的对象数组
Object[] newElements = Arrays.copyOf(elements, len + 1); // =========== 新对象数组
// 将元素添加到对象数组的末尾
newElements[len] = e;
// 替换内部对象数组的引用
setArray(newElements);
return true;
} finally {
// 解锁
lock.unlock();
}
}