Guide to the Java ArrayList – Java数组列表指南

最后修改: 2016年 9月 22日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this article, we’re going to take a look at ArrayList class from the Java Collections Framework. We’ll discuss its properties, common use cases, as well as its advantages and disadvantages.

在这篇文章中,我们将看一下Java集合框架中的ArrayList类。我们将讨论它的属性、常见的用例,以及它的优点和缺点。

ArrayList resides within Java Core Libraries, so you don’t need any additional libraries. In order to use it just add the following import statement:

ArrayList位于Java核心库中,所以你不需要任何额外的库。为了使用它,只需添加以下导入语句。

import java.util.ArrayList;

List represents an ordered sequence of values where some value may occur more than one time.

List表示一个有序的数值序列,其中一些数值可能出现不止一次。

ArrayList is one of the List implementations built atop an array, which is able to dynamically grow and shrink as you add/remove elements. Elements could be easily accessed by their indexes starting from zero. This implementation has the following properties:

ArrayList是建立在数组之上的List实现之一,它能够在你添加/删除元素时动态地增长和缩小。可以通过从零开始的索引轻松访问元素。这个实现有以下属性。

  • Random access takes O(1) time
  • Adding element takes amortized constant time O(1)
  • Inserting/Deleting takes O(n) time
  • Searching takes O(n) time for unsorted array and O(log n) for a sorted one

2. Create an ArrayList

2.创建一个ArrayList

ArrayList has several constructors and we will present them all in this section.

ArrayList有几个构造函数,我们将在本节中介绍它们。

First, notice that ArrayList is a generic class, so you can parameterize it with any type you want and the compiler will ensure that, for example, you will not be able to put Integer values inside a collection of Strings. Also, you don’t need to cast elements when retrieving them from a collection.

首先,注意到ArrayList是一个泛型类,所以你可以用任何你想要的类型对它进行参数化,编译器将确保,例如,你将不能把Integer值放在Strings的集合中。另外,当你从一个集合中检索元素时,你不需要对它们进行转换。

Secondly, it is good practice to use generic interface List as a variable type, because it decouples it from a particular implementation.

其次,使用通用接口List作为变量类型是一个很好的做法,因为它与特定的实现脱钩。

2.1. Default No-Arg Constructor

2.1.默认的无机关构造函数

List<String> list = new ArrayList<>();
assertTrue(list.isEmpty());

We’re simply creating an empty ArrayList instance.

我们只是在创建一个空的ArrayList实例。

2.2. Constructor Accepting Initial Capacity

2.2.接受初始容量的构造器

List<String> list = new ArrayList<>(20);

Here you specify the initial length of an underlying array. This may help you avoid unnecessary resizing while adding new items.

这里你可以指定一个底层数组的初始长度。这可以帮助你在添加新项时避免不必要的调整大小。

2.3. Constructor Accepting Collection

2.3.接受Collection的构造函数

Collection<Integer> numbers 
  = IntStream.range(0, 10).boxed().collect(toSet());

List<Integer> list = new ArrayList<>(numbers);
assertEquals(10, list.size());
assertTrue(numbers.containsAll(list));

Notice, that element of the Collection instance are used for populating the underlying array.

注意,Collection实例的元素被用来填充底层数组。

3. Add Elements to the ArrayList

3.向ArrayList添加元素

You may insert an element either at the end or at the specific position:

你可以在末尾或具体位置上插入一个元素。

List<Long> list = new ArrayList<>();

list.add(1L);
list.add(2L);
list.add(1, 3L);

assertThat(Arrays.asList(1L, 3L, 2L), equalTo(list));

You may also insert a collection or several elements at once:

你也可以一次插入一个集合或几个元素。

List<Long> list = new ArrayList<>(Arrays.asList(1L, 2L, 3L));
LongStream.range(4, 10).boxed()
  .collect(collectingAndThen(toCollection(ArrayList::new), ys -> list.addAll(0, ys)));
assertThat(Arrays.asList(4L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 3L), equalTo(list));

4. Iterate Over the ArrayList

4.迭代ArrayList

There are two types of iterators available: Iterator and ListIterator.

有两种类型的迭代器可用。IteratorListIterator

While the former gives you an opportunity to traverse the list in one direction, the latter allows you to traverse it in both directions.

前者让你有机会在一个方向上遍历名单,而后者则允许你在两个方向上遍历。

Here we will show you only the ListIterator:

这里我们将只向你展示ListIterator

List<Integer> list = new ArrayList<>(
  IntStream.range(0, 10).boxed().collect(toCollection(ArrayList::new))
);
ListIterator<Integer> it = list.listIterator(list.size());
List<Integer> result = new ArrayList<>(list.size());
while (it.hasPrevious()) {
    result.add(it.previous());
}

Collections.reverse(list);
assertThat(result, equalTo(list));

You may also search, add or remove elements using iterators.

你也可以使用迭代器搜索、添加或删除元素。

5. Search the ArrayList

5.搜索ArrayList

We will demonstrate how searching works using a collection:

我们将演示如何使用集合进行搜索。

List<String> list = LongStream.range(0, 16)
  .boxed()
  .map(Long::toHexString)
  .collect(toCollection(ArrayList::new));
List<String> stringsToSearch = new ArrayList<>(list);
stringsToSearch.addAll(list);

5.1. Searching an Unsorted List

5.1.搜索一个未排序的列表

In order to find an element you may use indexOf() or lastIndexOf() methods. They both accept an object and return int value:

为了找到一个元素,你可以使用indexOf()lastIndexOf()方法。它们都接受一个对象并返回int值。

assertEquals(10, stringsToSearch.indexOf("a"));
assertEquals(26, stringsToSearch.lastIndexOf("a"));

If you want to find all elements satisfying a predicate, you may filter collection using Java 8 Stream API (read more about it here) using Predicate like this:

如果你想找到所有满足谓词的元素,你可以使用Java 8 Stream API (在此阅读更多信息)使用Predicate这样过滤集合。

Set<String> matchingStrings = new HashSet<>(Arrays.asList("a", "c", "9"));

List<String> result = stringsToSearch
  .stream()
  .filter(matchingStrings::contains)
  .collect(toCollection(ArrayList::new));

assertEquals(6, result.size());

It is also possible to use a for loop or an iterator:

也可以使用一个for循环或一个迭代器。

Iterator<String> it = stringsToSearch.iterator();
Set<String> matchingStrings = new HashSet<>(Arrays.asList("a", "c", "9"));

List<String> result = new ArrayList<>();
while (it.hasNext()) {
    String s = it.next();
    if (matchingStrings.contains(s)) {
        result.add(s);
    }
}

5.2. Searching a Sorted List

5.2.搜索一个已排序的列表

If you have a sorted array, then you may use a binary search algorithm which works faster than linear search:

如果你有一个排序的数组,那么你可以使用二进制搜索算法,这种算法比线性搜索更快。

List<String> copy = new ArrayList<>(stringsToSearch);
Collections.sort(copy);
int index = Collections.binarySearch(copy, "f");
assertThat(index, not(equalTo(-1)));

Notice that if an element is not found then -1 will be returned.

注意,如果没有找到一个元素,那么将返回-1。

6. Remove Elements from the ArrayList

6.从ArrayList中删除元素

In order to remove an element, you should find its index and only then perform the removal via remove() method. An overloaded version of this method, that accepts an object, searches for it and performs removal of the first occurrence of an equal element:

为了删除一个元素,你应该找到它的索引,然后才通过remove()方法执行删除。这个方法的一个重载版本,它接受一个对象,搜索它并执行删除第一次出现的相等元素。

List<Integer> list = new ArrayList<>(
  IntStream.range(0, 10).boxed().collect(toCollection(ArrayList::new))
);
Collections.reverse(list);

list.remove(0);
assertThat(list.get(0), equalTo(8));

list.remove(Integer.valueOf(0));
assertFalse(list.contains(0));

But be careful when working with boxed types such as Integer. In order to remove a particular element, you should first box int value or otherwise, an element will be removed by its index.

但在处理盒式类型(如Integer)时要小心。为了删除一个特定的元素,你应该首先框定int值,否则,一个元素将按其索引被删除。

You may as well use the aforementioned Stream API for removing several items, but we won’t show it here. For this purpose we will use an iterator:

你也可以使用前面提到的Stream API来删除几个项目,但我们不会在这里展示它。为了这个目的,我们将使用一个迭代器。

Set<String> matchingStrings
 = HashSet<>(Arrays.asList("a", "b", "c", "d", "e", "f"));

Iterator<String> it = stringsToSearch.iterator();
while (it.hasNext()) {
    if (matchingStrings.contains(it.next())) {
        it.remove();
    }
}

7. Summary

7.总结

In this quick article, we had a look at the ArrayList in Java.

在这篇快速文章中,我们看了一下Java中的ArrayList。

We showed how to create an ArrayList instance, how to add, find or remove elements using different approaches.

我们展示了如何创建一个ArrayList实例,如何使用不同的方法添加、查找或删除元素。

As usual, you can find all the code samples over on GitHub.

像往常一样,你可以在GitHub上找到所有的代码样本超过