您的位置:首页 > 编程语言 > Java开发

Core Java Tutorial -- ArrayList

2018-03-19 20:42 429 查看
Java ArrayList 是最广泛使用的 Collection 类。
java.util.ArrayList
类实现类了
java.util.List
接口。Java ArrayList 也实现了
RandomAccess
Cloneable
Serializable
接口。Java ArrayList 类扩展了作为 List 接口的框架实现的
AbstractList
类。

Java ArrayList

Java ArrayList Constructors

Java ArrayList Methods

Java ArrayList Example

Java ArrayList common operations

Java ArrayList forEach

Java ArrayList Iterator

Java ArrayList ListIterator

Java ArrayList removeIf

Java ArrayList replaceAll

Java ArrayList subList

Java ArrayList Sorting

Thread Safe ArrayList

1. Java ArrayList

Java Array 是 List 接口的可调整大小的数组实现,这意味着它以默认大小开始并在将更多数据添加到数组列表中时自动增长。有关Java ArrayList 的一些重要观点有:

Java ArrayList 与 Vector 非常相似,只是它不同步,所以在单线程环境中性能更好。

Java ArrayList 不是线程安全的,因从在多线程环境中使用时必须特别小心。

Java ArrayList 可以包含重复值,它也允许 null 值。

Java ArrayList 中的对象按顺序添加。所以你总是可以通过索引 0 检索第一个对象。

Java ArrayList 默认容量定义为 10。但是,我们可以通过它的构造函数或调用
ensureCapacity(int minCapacity)
方法来更改默认容量。

Java ArrayList Iterator 和 ListIterator 实现是快速失败的。如果在以迭代器添加或删除方法之外的任何其他方式创建迭代器后修改了列表结构,则它将引发
ConcurrentModificationException
异常。

Java ArrayList 提供对其元素的随机访问,因为它对索引其作用。我们可以通过索引来检索任何元素。

Java ArrayList 支持泛型,它是推荐的创建 ArrayList 的方式。

List list = new ArrayList(); //not recommended
List<String> list1 = new ArrayList<String>(); // recommended way
List<String> list2 = new ArrayList<>();// diamond


1.1 Java ArrayList Constructors

Java ArrayList 类中有三个构造器:

1.
public ArrayList()
:最广泛使用的 Java ArrayList 构造函数。这个 ArrayList 构造函数将返回一个初始容量为 10 的空列表。

2.
public ArrayList(int initialCapacity)
:这个 ArrayList 构造函数将返回一个初始容量为空的列表,由 initialCapacity 参数指定。当你知道你的列表将包含大量数据,并且你希望通过提供大容量初始容量来节省重新分配时间时,这个构造函数非常有用。如果 initialCapacity 参数是负数,它将抛出
IllegalArgumentException
异常。

3.
public ArrayList(Collection<? extends E> c)
:这个 ArrayList 构造函数将按照集合迭代器返回的顺序返回包含指定集合元素的列表。如果指定的 Collection 参数为 null,它将抛出著名的
NullPointerException
空指针异常。

下面是一个简单的代码片段,展示了 Java ArrayList 构造函数的使用:

// Java ArrayList default constructor
List<String> vowels = new ArrayList<>();

//Java ArrayList constructor with initial capacity
List<String> dictionaryWordsList = new ArrayList<>(50000);

vowels.add("A");
vowels.add("E");
vowels.add("I");
vowels.add("O");
vowels.add("U");

//Creating my list from different collection source
List<String> myList = new ArrayList<>(vowels);


Java ArrayList Methods

public boolean add(E e)
:将指定的元素附加到此列表的末尾。

public void add(int index, E element)
:将指定的元素插入到列表中的指定位置。如果指定位置存在元素,则将后面的元素右移。如果索引大于列表大小或为负值,则会抛出
IndexOutOfBoundsException
异常。

public boolean addAll(Collection<? extends E> c)
:将指定集合的所有元素附加到此列表的末尾。按照它们由指定集合的​​ Iterator 返回的顺序。如果指定的集合为空,此操作将引发
NullPointerException
异常。

public boolean addAll(int index, Collection<? extends E> c)
:从指定位置开始,将指定集合中的所有元素插入到此列表中。如果指定位置存在元素,则将后面的元素右移。如果索引大于列表大小或为负值,则会抛出
IndexOutOfBoundsException
异常。如果指定的集合为 null,则此方法也会抛出
NullPointException
异常。

public boolean contains(Object o)
:如果此列表包含指定的元素,则返回 true。

public void clear()
:从此列表中移除所有元素。

public void ensureCapacity(int minCapacity)
:如有必要,增加此 ArrayList 实例的容量,以确保它至少可容纳由最小容量参数指定的元素数量。

public void forEach(Consumer<? super E> action)
:对 Iterable 的每个元素执行给定的操作,直到处理完所有元素或操作抛出异常。

public E get(int index)
:返回此列表中指定位置的元素。

public boolean isEmpty()
:如果此列表不包含任何元素,则返回 true。

public int indexOf(Object o)
:返回此列表中指定元素第一次出现的索引,如果此列表不包含这个元素,则返回 -1。

public Iterator<E> iterator()
:以正确的顺序返回此列表中元素的迭代器。返回的迭代器是快速失败的。

public int lastIndexOf(Object o)
: 返回此列表中指定元素最后一次出现的索引,如果此列表不包含该元素,则返回-1。

public ListIterator<E> listIterator()
:返回此列表中元素的列表迭代器(按正确顺序)。返回的列表迭代器是快速失败的。

public ListIterator<E> listIterator(int index)
:从列表中的指定位置开始,返回此列表中元素的列表迭代器(按正确顺序)。指定的索引指示将通过初始调用返回到下一个元素的第一个元素。对 previous 的初始调用将返回指定索引减 1 的元素。如果索引值大于列表大小或负值,则此方法抛出
IndexOutOfBoundsException
异常。

public E remove(int index)
:移除此列表中指定位置的元素。将后面的元素向全部左移(从其索引中减去一个元素)。

public boolean remove(Object o)
: 从列表中删除第一次出现的指定元素(如果存在)。如果该列表不包含该元素,则不变。

public boolean removeAll(Collection<E> c)
:从此列表中删除指定集合中包含的所有元素。

public boolean retainAll(Collection<E> c)
:只保留包含在指定集合中的列表中的元素。换句话说,从该列表中删除所有未包含在指定集合中的元素。

public boolean removeIf(Predicate<? super E> filter)
:移除此集合中满足给定谓词的所有元素。

public void replaceAll(UnaryOperator<E> operator)
:用将运算符应用于该元素的结果替换此列表中的每个元素。

public int size()
:返回此列表中元素的数量。

public E set(int index, E element)
用指定的元素替换此列表中指定位置的元素。

public List&
13a96
lt;E> subList(int fromIndex, int toIndex)
: 返回指定的fromIndex(包含)和toIndex(不包括)之间该列表部分的视图。返回的列表由此列表支持,因此返回列表中的非结构化更改将反映在此列表中,反之亦然。

public Spliterator<E> spliterator()
:在此列表中的元素上创建一个后期绑定和快速失败的Spliterator。

public void sort(Comparator<? super E> c)
:根据指定比较器引发的顺序对此列表进行排序。

public void trimToSize()
:将此ArrayList实例的容量修剪为列表的当前大小。应用程序可以使用此操作来最小化 ArrayList 实例的存储。

public Object[] toArray()
:以适当的顺序返回一个包含此列表中所有元素的数组(从第一个元素到最后一个元素)。 返回的数组将是“安全的”,因为此列表不会保留对它的引用。 (换句话说,这个方法必须分配一个新的数组)。调用者可以自由修改返回的数组。

public <T> T[] toArray(T[] a)
:以适当的顺序返回包含此列表中所有元素的数组。 如果列表适合指定的数组,它将按原样返回。否则,将使用指定数组的运行时类型和此列表的大小分配一个新数组。

2. Java ArrayList Example

让我们通过一些程序来看看 ArrayList 方法的例子。

2.1 Java ArrayList common operations

下面是一个简单的 Arraylist 示例程序,显示常用的方法。

package ArrayList;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ArrayListExample {

public static void main(String[] args) {
List<String> letters = new ArrayList<>();

// add example
letters.add("A");
letters.add("C");
letters.add("D");

// let's insert B between A and C
letters.add(1, "B");
System.out.println(letters);

List<String> list = new ArrayList<>();
list.add("E");
list.add("H");

// appending list elements to letters
letters.addAll(list);
System.out.println(letters);

// clear example to empty the list
list.clear();
System.out.println(list);

list.add("F");
list.add("G");

// inserting list inside letters to get right sequence
letters.addAll(5, list);
System.out.println(letters);

// contains example
System.out.println("Letters list contains E ?" + letters.contains("E"));
System.out.println("Letters list contains Z ?" + letters.contains("Z"));

// ensureCapacity example, it's ArrayList method, so object should be defined like below.
ArrayList<String> tempList = new ArrayList<>();
tempList.ensureCapacity(1000);

// get example
String e = letters.get(4);
System.out.println("Letter at 5th place: " + e);

// tempList is empty?
System.out.println("tempList is empty ? " + tempList.isEmpty());

// indexOf example
System.out.println("First index of D = " + letters.indexOf("D"));
System.out.println("Last index of D = " + letters.lastIndexOf("D"));

//remove examples
System.out.println(letters);
String removed = letters.remove(3);
System.out.println("After removing '" + removed + "' letters contains " + letters);

//remove first occurrence of H
boolean isRemoved = letters.remove("H");
System.out.println("H removed? " + isRemoved + ". Letters contains " + letters);
System.out.println("list contains " + list);

//remove all matching elements between letters and list
letters.removeAll(list);
System.out.println(letters);

//retainAll example
list.clear();
list.add("A");
list.add("B");
list.add("C");
letters.retainAll(list);
System.out.println("letters elements after retainAll operation: " + letters);

//size example
System.out.println("letters ArrayList size = " + letters.size());

//set example
letters.set(2, "D");
System.out.println(letters);

//toArray example
String[] strArray = new String[letters.size()];
strArray = letters.toArray(strArray);
System.out.println(Arrays.toString(strArray));
}
}


输出结果:

[A, B, C, D]
[A, B, C, D, E, H]
[A, B, C, D, E, F, G, H]
Letters list contains E ?true
Letters list contains Z ?false
Letter at 5th place: E
tempList is empty ? true
First index of D = 3
Last index of D = 3
[A, B, C, D, E, F, G, H]
After removing 'D' letters contains [A, B, C, E, F, G, H]
H removed? true. Letters contains [A, B, C, E, F, G]
list contains [F, G]
[A, B, C, E]
letters elements after retainAll operation: [A, B, C]
letters ArrayList size = 3
[A, B, D]
[A, B, D]


Java ArrayList forEach

Java 8 中添加了 Java ArrayList 的 forEach 方法。当你要对所有元素执行相同的操作时,非常有用。方法参数 Consumer 是一个函数接口,所以我们可以使用 lambda 表达式。下面是 forEach 方法的一个栗子,它显示了老方式以及 lambda 表达方式。

package ArrayList;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class ArrayListForEachExample {
public static void main(String[] args) {
List<String> stocks = new ArrayList<>();

stocks.add("Google");
stocks.add("Apple");
stocks.add("MicroSoft");
stocks.add("Facebook");

Consumer<Object> consumer = new ArrayListForEachExample().new MyConsumer();

stocks.forEach(consumer);

// lambda style
stocks.forEach(x -> {
System.out.println("Processed " + x);
});

}

class MyConsumer implements Consumer<Object> {

@Override
public void accept(Object t) {
System.out.println("Processing " + t);
}

}
}


ArrayList forEach 示栗程序输出如下:

Processing Google
Processing Apple
Processing MicroSoft
Processing Facebook
Processed Google
Processed Apple
Processed MicroSoft
Processed Facebook


Java ArrayList Iterator

Iterator 是 Java 集合框架中的一个接口。ArrayList 提供了快速失败迭代器的实现。当你相对所有列表元素执行一些操作使,你应该使用 Iterator。如果在迭代过程中对列表进行任何结构修改,则
next()
操作将抛出
ConcurrentModificationException
异常。下面是一个 ArrayList 迭代器的简单栗子。

package ArrayList;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ArrayListIteratorExample {
public static void main(String[] args) {
List<Integer> ints = new ArrayList<>();

for (int i = 0; i < 10; i++) {
ints.add(i);
}

Iterator<Integer> iterator = ints.iterator();

// simple iteration
while (iterator.hasNext()) {
int x = iterator.next();
System.out.print(x + ",");
}
System.out.println("\n" + ints);

// modification of list through iterator
iterator = ints.iterator();
while (iterator.hasNext()) {
int x = iterator.next();
if (x % 2 == 0) iterator.remove();
}
System.out.println(ints);

// changing list structure while iterating
iterator = ints.iterator();

while (iterator.hasNext()) {
int x = iterator.next();
// ConcurrentModificationException here
if (x == 5) {
ints.add(20);
}
}

}

}


上面 ArrayList 迭代器示例输出结果如下:

0,1,2,3,4,5,6,7,8,9,
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 3, 5, 7, 9]
Exception in thread "main"
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at List.ArrayListIteratorExample.main(ArrayListIteratorExample.java:39)


阅读更多关于 ConcurrentModificationException and how to avoid it

Java ArrayList ListIterator

我们可以使用 ListIterator 在两个方向上遍历列表,它允许我们删除以及添加一个元素到列表中。你还可以在 ListIterator 中获取迭代器的当前位置。让我们来看一个简单的 ArrayList ListIterator 示栗,用于向后遍历列表并修改列表数据。

package ArrayList;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ArrayListListIteratorExample {

public static void main(String[] args) {
List<Integer> ints = new ArrayList<>();
for (int i = 0; i < 10; i++) {
ints.add(i);
}

ListIterator<Integer> listIterator = ints.listIterator(ints.size());

while (listIterator.hasPrevious()) {
int x = listIterator.previous();
System.out.print(x + ", ");

if (x == 5) {
listIterator.remove();
listIterator.add(20);
}
}
System.out.println("\n" + ints);
}
}


注意上述程序的输出结果:

9, 8, 7, 6, 5, 20, 4, 3, 2, 1, 0,
[0, 1, 2, 3, 4, 20, 6, 7, 8, 9]


Java ArrayList removeIf

Java 8 中添加了 ArrayList removelf 方法。这个方法将删除列表中满足给定谓词的所有元素。我们来看一个 Java ArrayList removeIf 示例的简单程序。

package ArrayList;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class ArrayListRemoveIfExample {
public static void main(String[] args) {

List<Integer> integers = new ArrayList<>();

for (int i = 0; i < 10; i++) {
integers.add(i);
}

Predicate<Integer> filter = new ArrayListRemoveIfExample().new MyPredicate();

integers.removeIf(filter);
System.out.println(integers);

// lambda expression, remove elements divisible by 3
integers.removeIf(x -> x % 3 == 0);

/*        integers.removeIf(x -> {
return x % 3 == 0;
});*/
System.out.println(integers);
}

class MyPredicate implements Predicate<Integer> {

@Override
public boolean test(Integer t) {
return t % 2 == 0;
}

}
}


上述程序的输出结果如下:

[1, 3, 5, 7, 9]
[1, 5, 7]


Java ArrayList replaceAll

Java 8 中添加了ArrayList replaceAll 方法。当您想要在列表的所有元素上应用某个函数时,它非常有用。我们来看看 ArrayList replaceAll 示例程序。

package ArrayList;

import java.util.ArrayList;
import java.util.List;
import java.util.function.UnaryOperator;

public class ArrayListReplaceAllExample {

public static void main(String[] args) {
List<Integer> integers = new ArrayList<>();
for (int i = 0; i < 10; i++) {
integers.add(i);
}

// multiply all elements by 10
UnaryOperator<Integer> operator = new ArrayListReplaceAllExample().new MyUnaryOperator();
integers.replaceAll(operator);
System.out.println(integers);

// lambda expression example, multiply by 5
integers.replaceAll(integer -> integer * 5);

/*        integers.replaceAll(integer -> {
return integer * 5;
});*/
System.out.println(integers);
}

class MyUnaryOperator implements UnaryOperator<Integer> {

@Override
public Integer apply(Integer integer) {
return integer * 10;
}
}
}


上面 replaceAll 的示栗程序输出结果如下:

[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
[0, 50, 100, 150, 200, 250, 300, 350, 400, 450]


Java ArrayList subList

当我们对列表使用 subList 时,它将返回原始列表中的一部分视图。这个新列表由原始列表支持,因此任何修改都会反射到另一个列表中。如果支持列表在结构上以非返回列表的方式进行修改,则此方法返回的列表的语义变得未定义。新列表中的所有方法首先检查支持列表的实际 modCount 是否等于其预期值,如果不是,则抛出
ConcurrentModificationException
异常。让我们来用一个简单的 ArrayList subList 栗子来看这个行为。

package ArrayList;

import java.util.ArrayList;
import java.util.List;

public class ArrayListSubListExample {

public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Oktfolio");
names.add("David");
names.add("Lisa");
names.add("Meghna");

List<String> first2Names = names.subList(0, 2);

System.out.println(first2Names);

names.set(1, "Kumar");

// check the output below.
System.out.println(names + " , " + first2Names);

first2Names.add("Megan"); // this is fine

System.out.println(names + " , " + first2Names); // this is fine

// Let's modify the list size and get ConcurrentModificationException
names.add("Deepak");

System.out.println(names + " , " + first2Names); // this line throws exception
}
}


上面 ArrayList subList 的示栗程序输出结果如下:

[Oktfolio, David]
[Oktfolio, Kumar, Lisa, Meghna] , [Oktfolio, Kumar]
[Oktfolio, Kumar, Megan, Lisa, Meghna] , [Oktfolio, Kumar, Megan]
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1239)
at java.util.ArrayList$SubList.listIterator(ArrayList.java:1099)
at java.util.AbstractList.listIterator(AbstractList.java:299)
at java.util.ArrayList$SubList.iterator(ArrayList.java:1095)
at java.util.AbstractCollection.toString(AbstractCollection.java:454)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at ArrayList.ArrayListSubListExample.main(ArrayListSubListExample.java:31)


Java ArrayList Sorting

我们可以使用 ArrayList sort 方法对其元素进行排序。下面是一个展示 ArrayList 排序的简单示:

package ArrayList;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Random;

public class ArrayListSortingExample {

public static void main(String[] args) {
List<Integer> integers = new ArrayList<>();

Random random = new Random();

for (int i = 0; i < 10; i++) {
integers.add(random.nextInt(1000));
}

System.out.println("Origin List: " + integers);

// sort the list
MyComparator comparator = new ArrayListSortingExample().new MyComparator();
integers.sort(comparator);

System.out.println("Sorted in Increasing Order: " + integers);

// lambda example, sort in reverse order
integers.sort((o1, o2) -> o2 - o1);

/*        integers.sort((o1, o2) -> {
return o2 - o1;
});*/

System.out.println("Sorted in Decreasing Order: " + integers);

}

class MyComparator implements Comparator<Integer> {

@Override
public int compare(Integer o1, Integer o2) {
return (o1 - o2);
}
}
}


上面排序程序的输出结果如下:

Origin List: [555, 683, 62, 59, 199, 579, 679, 188, 304, 968]
Sorted in Increasing Order: [59, 62, 188, 199, 304, 555, 579, 679, 683, 968]
Sorted in Decreasing Order: [968, 683, 679, 579, 555, 304, 199, 188, 62, 59]


Thread Safe ArrayList

Java ArrayList 不是线程安全的。所以如果你在多线程环境用使用它的话,用下面的代码来获得线程安全的 ArrayList 。

List<Integer> synchronizedList = Collections.synchronizedList(ints);


在这种情况下,你也可以使用 CopyOnWriteArrayList 并发结合类。

这就是 Java ArrayList 示栗教程的全部内容。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: