java中常见的List

本文详细对比了ArrayList、LinkedList、Vector及CopyOnWriteArrayList等List容器的特点,并分析了它们的线程安全性、容量调整机制及适用场景。此外,还介绍了跳跃列表这一高级数据结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、线程不安全的List

ArrayList

特点:

  • 有点:查询和更新元素值比较快。
  • 缺点:添加或删除一个元素需要移动数组中的其它元素。

容量:

  • 初始容量:0
  • 扩容:
    • 调用add方法时,若ArrayList中元素的数量(size)等于等于对象数组(elementData)的长度时会触发扩容操作,容量第一次扩展为10,之后每次扩展为之前的1.5倍。调用remove方法,不会进行缩容操作。
    • 代码:
      • 扩容1.5倍: newCapacity = oldCapacity + (oldCapacity >> 1);
      • 扩容时对数组进行复制:elementData = Arrays.copyOf(elementData, newCapacity);
    •  说明:
      • 虽然ArrayList类的初始容量默认为10(private static final int DEFAULT_CAPACITY = 10;)
      • 但实际上在new ArrayList()后,ArrayList的elementData(transient Object[] elementData;)的length为0
      •  在第一次调用add方法时,elementData的length才初始化为10。      

LinkedList

二、线程安全的List

Collections.synchronizedList(List list)

举例:

  • List<String> syncArraylist = Collections.synchronizedList(new ArrayList<String>());    
  • List<String> syncLinkedList = Collections.synchronizedList(new LinkedList<String>());

说明:

  • Collections.synchronizedList(List list)实际上是创建了一个java.util.Collections的内部类SynchronizedList。
  • SynchronizedList只是在自己的方法中使用同步代码块将List(封装的ArrayList、linkedList等)里相应的方法包裹了起来,故SynchronizedList的扩容方式同它封装的list一样。
  • SynchronizedList还可以指定锁对象,如不指定,默认为this。

CopyOnWriteArrayList:

  • 使用ReentrantLock来实现线程的同步。
  • 每添加一个元素,就进行一次数组的copy,故CopyOnWriteArrayList的写性能非常的糟糕。
  • 多线程环境下,CopyOnWriteArrayList的读性能比Collections.SynchronizedList的读性能好一些(后者的get方法也被同步代码块包裹了,故读性能稍差一点)。

Vector

线程安全:

  • Vector是线程安全的(方法是Synchronized的)

容量:

  • 初始容量:10    

扩容:

  • 每次扩展为之前的2倍。
  • 代码:
    • 扩容2倍: int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); // capacityIncrement默认为0 
    • 扩容时对数组进行复制: elementData = Arrays.copyOf(elementData, newCapacity);

三、ArrayList VS Vector

不同点:

  • ArrayList非线程安全,Vector线程安全。
  • ArrayList扩容后容量变为之前的1.5倍,Vector扩容后容量是之前的2倍,故ArrayList更省空间。  

相同点:

  • 都是基于Object数组实现的。
  • 都允许添加null元素。 

四、ArrayList VS LinkedList

不同点:

  • 对于随机访问get和set,ArrayList比LinkedList快。
  • 对于插入和删除操作,LinkedList比较快。

相同点:

  • 都允许添加null元素。

结论:

  • 从时间复杂度来说:如果对list增加或删除操作较多,则建议使用LinkedList;如果对list查询操作较多,则建议使用ArrayList。
  • 从空间复杂度来说:LinkedList占用的空间较多(链表中的每一个节点都需要两个引用来指向它的previous节点和next节点)。

五、跳跃列表

跳跃列表

### Java List 使用教程与常用操作示例 Java 中的 `List` 是一个有序的集合,允许存储重复的元素,并且可以通过索引访问。`List` 接口是 `Collection` 接口的子接口,因此它继承了 `Collection` 接口的所有方法,并在此基础上扩展了一些特有的方法,使其更适合处理有序的集合。 #### 初始化 List 可以使用多种方式来初始化一个 `List`,常见几种方式如下: - **使用 `ArrayList` 初始化并添加元素**: ```java List<String> languages = new ArrayList<>(); languages.add("Java"); languages.add("PHP"); languages.add("Python"); ``` - **使用 `Arrays.asList` 方法**: ```java List<String> stringList = Arrays.asList("a", "b", "c"); ``` - **使用 `Lists.newArrayList`(来自 Guava 库)**: ```java List<String> list = Lists.newArrayList("a", "b", "c"); ``` - **使用双括号初始化**: ```java List<String> languages = new ArrayList<>() { { add("Java"); add("PHP"); add("Python"); } }; ``` #### 常用操作 以下是一些 `List` 的常用操作及其示例代码: - **获取集合内元素个数**: ```java int size = list.size(); ``` - **添加元素**: - 默认添加: ```java list.add("Java"); ``` - 指定下标添加: ```java list.add(1, "Python"); ``` - **删除元素**: - 删除指定元素: ```java boolean isRemoved = list.remove("Java"); ``` - 删除指定下标的元素: ```java list.remove(0); ``` - **替换元素**: ```java list.set(0, "C++"); ``` - **取出元素**: ```java String element = list.get(0); ``` - **清空集合**: ```java list.clear(); ``` - **判断集合中是否存在某个元素**: ```java boolean contains = list.contains("Java"); ``` - **对比两个集合中的所有元素**: - 两个对象一定相等: ```java boolean isEqual = list.equals(list2); ``` - 两个对象不一定相等: ```java boolean isHashCodeEqual = list.hashCode() == list2.hashCode(); ``` - **获得元素下标**: - 获取第一个匹配元素的下标: ```java int index = list.indexOf("Java"); ``` - 获取最后一个匹配元素的下标: ```java int lastIndex = list.lastIndexOf("Java"); ``` - **判断集合是否为空**: ```java boolean isEmpty = list.isEmpty(); ``` - **返回 `Iterator` 集合对象**: ```java Iterator<String> iterator = list.iterator(); ``` - **将集合转换为字符串**: ```java String listString = list.toString(); ``` - **截取集合**: ```java List<String> subList = list.subList(0, 2); ``` - **将集合转换为数组**: - 默认类型: ```java Object[] array = list.toArray(); ``` - 指定类型: ```java String[] stringArray = list.toArray(new String[0]); ``` #### 示例代码 以下是一个完整的示例,展示了如何定义一个包含自定义对象的 `List` 并进行一些基本操作: ```java // 定义一个 Model 类 public class Model { private String id; private String code; private String name; private BigDecimal bonus; // 构造方法、getter 和 setter 省略 } // 定义并初始化一个 List List<Model> list = new ArrayList<>(); Model model1 = new Model(); model1.setId("1"); model1.setCode("A"); model1.setName("Model A"); model1.setBonus(new BigDecimal("100.00")); list.add(model1); // 添加更多元素 Model model2 = new Model(); model2.setId("2"); model2.setCode("B"); model2.setName("Model B"); model2.setBonus(new BigDecimal("200.00")); list.add(model2); // 遍历 List for (Model model : list) { System.out.println(model.getName()); } // 删除元素 list.remove(model1); // 检查是否为空 if (list.isEmpty()) { System.out.println("List is empty."); } else { System.out.println("List is not empty."); } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值