List 相关常见知识

ArrayList 和 Array(数组)的区别?

ArrayList 内部基于动态数组实现,比 Array(静态数组) 使用起来更加灵活:

 // 初始化一个 String 类型的数组
 String[] stringArr = new String[]{"hello", "world", "!"};
 // 修改数组元素的值
 stringArr[0] = "goodbye";
 System.out.println(Arrays.toString(stringArr));// [goodbye, world, !]
 // 删除数组中的元素,需要手动移动后面的元素
 for (int i = 0; i < stringArr.length - 1; i++) {
     stringArr[i] = stringArr[i + 1];
 }
 stringArr[stringArr.length - 1] = null;
 System.out.println(Arrays.toString(stringArr));// [world, !, null]
// 初始化一个 String 类型的 ArrayList
 ArrayList<String> stringList = new ArrayList<>(Arrays.asList("hello", "world", "!"));
// 添加元素到 ArrayList 中
 stringList.add("goodbye");
 System.out.println(stringList);// [hello, world, !, goodbye]
 // 修改 ArrayList 中的元素
 stringList.set(0, "hi");
 System.out.println(stringList);// [hi, world, !, goodbye]
 // 删除 ArrayList 中的元素
 stringList.remove(0);
 System.out.println(stringList); // [world, !, goodbye]

ArrayList 与 LinkedList 区别?

一般不会使用 LinkedList ,需要用到 LinkedList 的场景几乎都可以使用 ArrayList 来代替,并且,性能通常会更好。

RandomAccess 接口

Question

Q: LinkedList 为什么不能实现 RandomAccess 接口?
A: RandomAccess 是一个标记接口,用来表明实现该接口的类支持随机访问(即可以通过索引快速访问元素)。由于 LinkedList 底层数据结构是链表,内存地址不连续,只能通过指针来定位,不支持随机快速访问,所以不能实现 RandomAccess 接口。

public interface RandomAccess {
}

实际上 RandomAccess 接口中什么都没有定义。所以 RandomAccess 接口不过是一个标识罢了。 标识实现这个接口的类具有随机访问功能

binarySearch() 方法中,它要判断传入的 list 是否 RandomAccess 的实例,如果是,调用 indexedBinarySearch()方法,如果不是,那么调用 iteratorBinarySearch()方法

双向链表与双向循环链表

|450

|450

ArrayList 插入和删除元素的时间复杂度?

非常好理解,复杂度和想象一样,和数组本质也一样。

插入:

删除:

LinkedList 插入和删除元素的时间复杂度?

LinkList 为双向链表,值得注意。

了解(看看就行,较为简单):

ArrayList 和 Vector 的区别?(了解即可)

Vector 和 Stack 的区别?(了解即可)

Note

随着 Java 并发编程的发展,VectorStack 已经被淘汰,推荐使用并发集合类(例如 ConcurrentHashMapCopyOnWriteArrayList 等)或者手动实现线程安全的方法来提供安全的多线程操作支持。

ArrayList 可以添加 null 值吗?

ArrayList 中可以存储任何类型的对象,包括 null 值。不过,不建议向 ArrayList 中添加 null 值, null 值无意义,会让代码难以维护比如忘记做判空处理就会导致空指针异常。