1.什么是ArrayList?

ArrayList是个动态数组,实现List接口,主要用来存储数据,如果存储基本类型的数据,如int,long,boolean,short,byte,那只存储它们对应的包装类。它的特点是:

增删慢:每次删除元素,都需要更改数组长度、拷贝以及移动元素位置。

查询快:由于数组在内存中是一块连续空间,因此可以根据地址+索引的方式快速获取对应位置上的元素。

2.ArrayList线程安全吗?

ArrayList是线程不安全的。

当开启多个线程操作List集合,向ArrayList中增加元素,同时去除元素。最后输出list中的所有数据,会出现几种情况:

①有些元素输出为Null;②数组下标越界异常。

有两种解决方案:

第一种是选用线程安全的数组容器是Vector,它将所有的方法都加上了synchronized。

public static Vector<Object> vector= new Vector<Object>(); 

第二种是用Collections.synchronizedList将ArrayList包装成线程安全的数组容器。

List<String> list = Collections.synchronizedList(new ArrayList<>());

为什么ArrayList线程不安全,我们还使用它?

因为大多数的场景中,查询操作使用频率高,增删操作的使用频率低。如果涉及频繁的增删,可以使用LinkedList,实际开发过程中还是ArrayList使用最多的。 不存在一个集合既查询效率高,又增删效率高,还线程安全的,因为数据结构的特性就是优劣共存的,想找个平衡点很难,牺牲了性能,那就安全,牺牲了安全那就快速。

3.ArrayList默认的数组大小是多少?

private static final int DEFAULT_CAPACITY = 10;

ArrayList默认数组大小是10。

    public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}

默认的构造方法,构造一个初始容量为10的空列表。

4.ArrayList如何扩容?

ArrayList的扩容主要发生在向ArrayList集合中添加元素的时候,通过add()方法添加单个元素时,会先检查容量,看是否需要扩容。如果容量不足需要扩容则调用grow()扩容方法,扩容后的大小等于扩容前大小的1.5倍,也就是10+10/2。比如说超过10个元素时,会重新定义一个长度为15的数组。然后把原数组的数据,原封不动的复制到新数组中,这个时候再把指向原数的地址换到新数组。

// grow扩容方法
private void grow(int minCapacity) {// 记录扩容前的数组长度int oldCapacity = elementData.length;// 位运算,右移动一位。 整体相当于newCapacity =oldCapacity + 0.5 * oldCapacityint newCapacity = oldCapacity + (oldCapacity >> 1);// 如果扩容后的长度小于当前的数据量,那么就将当前的数据量的长度作为本次扩容的长度if (newCapacity - minCapacity < 0)newCapacity = minCapacity;// 判断新数组的长度是否大于可分配数组的最大值if (newCapacity - MAX_ARRAY_SIZE > 0)// 将扩容长度设置为最大可用长度newCapacity = hugeCapacity(minCapacity);// 拷贝,扩容,构建一个新的数组elementData = Arrays.copyOf(elementData, newCapacity);
}

5.ArrayList<String> list = new ArrayList<>(20); 中的list扩充几次?

不需要扩容。当指明了需要多少空间时,会一次性分配这么多的空间,就不需要扩容了。

    public ArrayList(int initialCapacity) {//判断initialCapacity是否大于0if (initialCapacity > 0) {//创建一个数组,且指定长度为initialCapacitythis.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {//如果initialCapacity容量为0,把EMPTY_ELEMENTDATA的地址赋值给elementDatathis.elementData = EMPTY_ELEMENTDATA;// 如果初始容量小于0,则会出现 IllegalArgumentException 异常} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}

6.ArrayList频繁扩容导致添加性能急剧下降,如何处理?

使用ArrayList时,可以 new ArrayList(大小)构造方法来指定集合的大小,以减少扩容的次数,提高写入效率。

7.ArrayList插入或删除元素一定比LinkedList慢么?

取决于删除的元素离数组末端有多远,ArrayList拿来作为堆栈来用还是挺合适的,push和pop操作完全不涉及数据移动操作。

8.如何复制某个ArrayList到另一个ArrayList中去?

(1)使用clone()方法

    public static void main(String[] args) {ArrayList<String> list = new ArrayList<String>();list.add("云");list.add("烟");list.add("成");list.add("雨");Object o = list.clone();System.out.println(o);System.out.println(list);}

运行结果

源码分析:

    public Object clone() {try {ArrayList<?> v = (ArrayList<?>) super.clone();v.elementData = Arrays.copyOf(elementData, size);v.modCount = 0;return v;} catch (CloneNotSupportedException e) {// this shouldn't happen, since we are Cloneablethrow new InternalError(e);}}

(2)使用ArrayList构造方法

    public static void main(String[] args) {ArrayList<String> list = new ArrayList<String>();list.add("aaa");list.add("bbb");list.add("ccc");ArrayList<String> list1 = new ArrayList<>(list);for (String s : list1) {System.out.println(s);}}

运行结果

源码分析:

    public ArrayList(Collection<? extends E> c) {// 将集合构造中的集合对象转成数组,且将数组的地址赋值给elementDataelementData = c.toArray();// 将elementData的长度赋值给 集合长度size,且判断是否不等于 0if ((size = elementData.length) != 0) {// 判断elementData 和 Object[] 是否为不一样的类型if (elementData.getClass() != Object[].class)//如果不一样,使用Arrays的copyOf方法进行元素的拷贝elementData = Arrays.copyOf(elementData, size, Object[].class);} else {// 用空数组代替this.elementData = EMPTY_ELEMENTDATA;}}

(3)使用addAll方法

    public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("Hello");list.add("world");list.add("!");ArrayList<String> list1 = new ArrayList<>();list1.addAll(list);System.out.println(list);System.out.println(list1);}

运行结果

源码分析:

    public boolean addAll(Collection<? extends E> c) {//把集合的元素转存到Object类型的数组中Object[] a = c.toArray();//记录数组的长度int numNew = a.length;//调用方法检验是否要扩容,且让增量++ensureCapacityInternal(size + numNew); //调用方法将a数组的元素拷贝到elementData数组中System.arraycopy(a, 0, elementData, size, numNew);//集合的长度+=a数组的长度size += numNew;//只要a数组的长度不等于0,即说明添加成功return numNew != 0;}

9.ArrayList用来做队列合适么?

队列一般是FIFO(先入先出)的,如果用ArrayList做队列,需要在数组尾部追加数据,数组头部删除数组,反过来也可以。但是无论如何总会有一个操作会涉及到数组的数据搬迁,这个是比较耗费性能的。

虽然ArrayList不适合做队列,但是数组是非常合适的。比如ArrayBlockingQueue内部实现就是一个环形队列,它是一个定长队列,内部是用一个定长数组来实现的。另外著名的Disruptor开源Library也是用环形数组来实现的超高性能队列,具体原理不做解释,比较复杂。简单点说就是使用两个偏移量来标记数组的读位置和写位置,如果超过长度就折回到数组开头,前提是它们是定长数组。

10.ArrayList和LinkedList的区别?

ArrayList:

  • 基于动态数组的数据结构
  • 对于随机访问的get和set,ArrayList要优于LinkedList
  • 对于随机操作的add和remove,ArrayList不一定比LinkedList慢 (ArrayList底层由于是动态数组,因此并不是每次add和remove的时候都需要创建新数组)

LinkedList:

  • 基于双向链表的数据结构(双向链表遍历效率可能优于单向链表,因为双向链表可以在查找元素时,判断靠近头还是靠近尾,如果靠近头从头开始找,如果靠近尾从尾开始找)
  • 对于顺序操作,LinkedList不一定比ArrayList慢
  • 对于随机操作,LinkedList效率明显较低

arraylist 线性不安全_Java面试系列(一)--集合类ArrayList相关推荐

  1. spring cloud每次修改必须重新打包_Java面试系列spring相关

    Spring中的Bean是线程安全的吗? Spring 中的 bean 默认都是单例的,所有线程都共享一个单例实例Bean,因此是存在资源的竞争,是线程不安全的. 但是spring中大部分bean都是 ...

  2. Java文件和文件夹的区别_Java面试系列-webapp文件夹和WebContent文件夹的区别?-kingsoft是什么文件夹...

    我的程序员面试系列 面试题:Java Web Project里我们会遇到下面两种文件夹:webapp和WebContent. 这两个文件夹下都有个字文件夹WEB-INF,里面都有web.xml.为什么 ...

  3. arraylist线程安全吗_Java面试复习-IO和多线程

    IO 流 java 中有几种类型的流 按照流方向:输入流 输出流 按照处理数据单位: 字节流,字符流 字节流和字符流的区别 字节流读取的时候,读到一个字节就返回一个字节 字符流对读取多个字节时会先去查 ...

  4. 小红书java算法难吗_Java面试系列之记一次小红书之旅

    一面一面面试官看着二十七八岁,文质彬彬,这哪里是写代码的,头发都飘起来了好么.上来就干项目,由于大家的项目都不太一样,所以对于项目部分我就说说我面试的时候经常遇到的问题描述下项目一口是吃不了胖子的,描 ...

  5. 静态导入 java面试_Java面试系列【静态导入】-静态导入,基础篇

    import是学习Java的人最熟悉不过的语句了,我们通过import语句导入类.但实际上我们对于import还有其他用法. import static 看一段代码: import java.util ...

  6. java map 面试题_Java 面试系列:集合详解之 Map + 面试题

    集合有两个大接口:Collection 和 Map,本文重点来讲解集合中另一个常用的集合类型 Map. 以下是 Map 的继承关系图: avatar Map 简介 Map 常用的实现类如下: Hash ...

  7. arraylist线程安全吗_java集合----超详细图解(ArrayList线程安全解决三种解决方法!)...

    (注意:多线程情况下的判断,如果你能确定就两个线程(不包括main主线程或者是说GC),判断可以用if,但如果是多个线程则用while,否则会出现错误)ArrayList线程安全的几个问题解决(Has ...

  8. Android面试系列文章2018之内存管理之UI卡顿篇

    Android面试系列文章2018之内存管理之UI卡顿篇 1.UI卡顿的原理   60ftp –> 16ms: Android系统每隔16ms都会对界面进行渲染一次,造成卡顿的原因就是Andro ...

  9. 万万没想到!!! 谷歌面试原来也问ArrayList

    不花时间的导读:这是<好好面试系列>第27篇原创文,该系列主要分享小饭饭面试别人.和被别人面试的经历,该篇文章主要分享ArrayList高频面试题,有兴趣的看看,已经知道的可以无视. 前几 ...

  10. Android 面试系列 Dn.1---- Service?

    Yo....Yo..Yo... 各位学zha老爷们好,我是靠颜值混日子的榴莲欧巴,欢迎学zha老爷们按时来阅读今天的 Android面试系列.如果您是一个年龄小于24岁妹纸,一定要关注微信公众号&qu ...

最新文章

  1. error: Can not locate config makefile for product “xx“.
  2. [转] 2016前端开发技术巡礼
  3. wsl开nginx和php-fpm遇到的几个小问题
  4. IT项目十大灾难(转载)
  5. IAR stm32中函数硬是要加上声明才能编译通过,记录一下
  6. 以mips为单位衡量微型计算机的性能,2016计算机二级《MS Office》选择题专项训练...
  7. android 退出应用没有走ondestory方法,Android退出应用最优雅的方式(改进版)
  8. nobelking 3 js 数字和数字相加 字符串连接 数字和字符串连接1
  9. linux视音频解码教程,音视频编解码:NVIDIA Jetson Linux Multimedia API(总结)
  10. HDC.2019后再发力,AppGallery Connect服务新升级
  11. Java 进栈出栈的过程
  12. 初识好朋友计算机课件,-精选版初识我们的好朋友——计算机.ppt
  13. webpack初体验_使用webpack打包js文件_json文件_使用webpack开发模式_生产模式打包---webpack工作笔记003
  14. 【数学建模】基于matlab细胞传输模型实现交通流【含Matlab源码 376期】
  15. Spring4新特性——泛型限定式依赖注入
  16. authware课件
  17. 我的世界服务器显示fps,我的世界帧数优化攻略 低配、fps低玩家必看
  18. 每次遇到浏览器主页被篡改的问题,就特别气愤加头疼
  19. git强制拉取最新代码
  20. Java面试题及答案整理-肝天-肝帝-干面试管~

热门文章

  1. 16.卷1(套接字联网API)---非阻塞式IO
  2. 7. HTTP 请求,响应
  3. 智慧屏鸿蒙系统简介,首发鸿蒙系统,荣耀智慧屏是何方神圣?
  4. 新公司入职56天后的面谈小结
  5. python中json怎么转换成字典
  6. iOS 新浪微博-5.3 首页微博列表_集成图片浏览器
  7. ZOJ 2412 Farm Irrigation
  8. 微信小程序——诉讼费计算
  9. idea导入项目常见异常处理
  10. 端口映射--PortTunnel