Java ArrayList 使用和常见面试题

继承关系

ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。

ArrayList 继承了 AbstractList ,并实现了 List 接口。

Java ArrayList 使用和常见面试题

  • 类的导入
import java.util.ArrayList; // 引入 ArrayList 类
ArrayList<E> objectName =new ArrayList<>();  // 初始化

E 是泛型数据类型,只能为 引用数据类型

基本类型 引用类型
boolean Boolean
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
ArrayList<Integer> li=new Arraylist<>();     // 存放整数元素
ArrayList<Character> li=new Arraylist<>();   // 存放字符元素

队列操作

import java.util.ArrayList;

public class RunoobTest {
    public static void main(String[] args) {
        ArrayList<String> sites = new ArrayList<String>();
        
        // 基本操作
        sites.add("Google"); // add(e) 添加元素
        sites.add("Runoob");
        sites.get(1); // get(index) 访问元素
        sites.set(1, "Wiki"); // set(index, e) 修改元素
        sites.remove(3); // remove(index) 删除元素
        sites.remove("Google"); // remove(e) 删除元素
        sites.size(); // 计算大小
        
        // 数组迭代
         for (int i = 0; i < sites.size(); i++) { // 下标迭代
            System.out.println(sites.get(i));
        }       
        for (String i : sites) { // for-each 迭代
            System.out.println(i);
        }
        for (Iterator<String> it = list.iterator(); it.hasNext(); ) { // 迭代器迭代
            // 通过 Iterator 遍历 List 永远是最高效的方式
            // Java 的 for each 循环本身就可以帮我们使用 Iterator 遍历
            String s = it.next();
            System.out.println(s);
        }
    }
}

队列排序

使用 Collections 类中提供的 sort() 方法

import java.util.ArrayList;
import java.util.Collections;  // 引入 Collections 类

ArrayList<String> sites = new ArrayList<String>();
Collections.sort(sites);  // 字母排序

ArrayList<Integer> myNumbers = new ArrayList<Integer>();
Collections.sort(myNumbers);  // 数字排序

面试问题

  • ArrayList 插入删除一定慢么?

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

  • ArrayList 的遍历和 LinkedList 遍历性能比较如何?

ArrayList 要比 LinkedList 快得多。ArrayList 遍历最大的优势在于内存的连续性,根据程序局部性原理 CPU chche 会缓存连续内存片段,可以大幅降低读取内存性能开销。

  • ArrayList 是如何扩容的?

首先分配一个原来大小 1.5 倍的内存空间,然后把原来的数组进行拷贝

  • ArrayList 是线程安全的么?哪些是线程安全的?

不是。源码中 elementData[size++] = e; 分为两步,elementData[size]=e ; size++; 这两步不上锁的情况下可能会出现值覆盖而有些元素值为 null 的情况。

线程安全

  • 使用 Vector进行替换

List arrayList = new ArrayList() 替换为 List arrayList = new Vector<>();

原理:使用了 synchronized 关键字进行了加锁处理

public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
 }
  • 使用 Collections.synchronizedList(List) 进行替换

List arrayList = Collections.synchronizedList(new ArrayList());

原理:使用 mutex对象进行维护处理

// SynchronizedList类如下
    static class SynchronizedList<E> extends SynchronizedCollection<E> implements List<E> {
        	// 其中的add方法如下
        	public void add(int index, E element) {
            synchronized (mutex) {list.add(index, element);}
        	}
        }
  • java.util.concurrent包中CopyOnWriteArrayList 类进行替换

List arrayList = new CopyOnWriteArrayList<>();

参考链接

Java ArrayList

坑人无数的 Java 面试题之 ArrayList

ArrayList 线程安全问题

使用 Concurrent 集合

上一篇:c#-特殊的集合-BitArray-bitArray.Not()-简单实验


下一篇:操作集合的工具类