Java ArrayList指南

评论 0 浏览 0 2016-09-23

1.概述

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

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

import java.util.ArrayList;

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

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

  • 随机访问需要O(1)时间
  • 添加元素需要分摊恒定的时间O(1)
  • 插入/删除需要O(n)时间。
  • 对于未排序的数组,搜索需要O(n)的时间,而对于排序的数组,则需要O(log n)

2.创建一个ArrayList

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

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

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

2.1.默认的无参数构造函数

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

我们只是简单地创建一个空的ArrayList实例。

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

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

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

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));

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

3.将元素添加到ArrayList

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

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

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

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

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

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.遍历ArrayList

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

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

在这里,我们将只向你展示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));

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

5.搜索ArrayList的内容

我们将用一个集合来演示搜索的工作原理。

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.搜索未排序的列表

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

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

如果您想找到满足谓词的所有元素,您可以使用 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());

也可以使用一个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.搜索一个已分类的列表

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

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

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

6.从ArrayList中删除元素

为了删除一个元素,你应该找到它的索引,然后才通过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));

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

你也可以使用前面提到的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.摘要

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

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

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

最后更新2023-10-23
0 个评论
标签