Arrays in Java: A Reference Guide – Java中的数组 参考指南

最后修改: 2018年 10月 30日

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

1. Introduction

1.绪论

In this tutorial, we’ll deep dive into a core concept in the Java language – arrays.

在本教程中,我们将深入研究Java语言中的一个核心概念–数组。

We’ll first see what’s an array, then how to use them; overall, we’ll cover how to:

我们首先会看到什么是数组,然后是如何使用它们;总的来说,我们会涵盖如何。

  • Get started with arrays
  • Read and write arrays elements
  • Loop over an array
  • Transform arrays into other objects like List or Streams
  • Sort, search and combine arrays

2. What’s an Array?

2.什么是阵列?

First things first, we need to define what’s an array? According to the Java documentation, an array is an object containing a fixed number of values of the same type. The elements of an array are indexed, which means we can access them with numbers (called indices).

首先,我们需要定义什么是数组?根据Java文档,数组是一个包含固定数量的相同类型的值的对象。数组的元素是有索引的,这意味着我们可以用数字(称为indices)来访问它们。

We can consider an array as a numbered list of cells, each cell being a variable holding a value. In Java, the numbering starts at 0.

我们可以把数组看作是一个有编号的单元格列表,每个单元格都是持有一个值的变量。在Java中,编号从0开始。

There are primitive type arrays and object type arrays. This means we can use arrays of int, float, boolean, … But also arrays of String, Object and custom types as well.

有原始类型数组和对象类型数组。这意味着我们可以使用int, float, boolean, …的数组,但也可以使用String, Object和自定义类型的数组。

3. Setting up an Array

3.设置一个阵列

Now that arrays are well-defined, let’s dive into their usages.

现在,数组已经有了明确的定义,让我们深入了解其用途。

We’ll cover a lot of topics teaching us how to use arrays. We’ll learn some basics like how to declare and initialize an array, but we’ll also cover more advanced subjects like sorting and searching arrays.

我们将涵盖很多教我们如何使用数组的主题。我们将学习一些基础知识,如如何声明和初始化数组,但我们也会涉及更高级的课题,如排序和搜索数组。

Let’s go first with declaration and initialization.

我们先来看看声明和初始化。

3.1. Declaration

3.1.声明

We’ll begin with the declaration. There are two ways to declare an array in Java:

我们先从声明开始。在Java中声明一个数组有两种方法。

int[] anArray;

or:

或。

int anOtherArray[];

The former is more widely used than the latter.

前者比后者使用更广泛

3.2. Initialization

3.2.初始化

Now that it’s time to see how to initialize arrays. Again there are multiple ways to initialize an array. We’ll see the main ones here, but this article covers arrays initialization in detail.

现在,是时候看看如何初始化数组了。同样,有多种方法来初始化数组。我们将在这里看到主要的方法,但是这篇文章详细介绍了数组的初始化。

Let’s begin with a simple way:

让我们从一个简单的方法开始。

int[] anArray = new int[10];

By using this method, we initialized an array of ten int elements. Note that we need to specify the size of the array.

通过使用这个方法,我们初始化了一个包含十个int元素的数组。请注意,我们需要指定数组的大小。

When using this method, we initialize each element to its default value, here 0. When initializing an array of Object, elements are null by default.

当使用此方法时,我们将每个元素初始化为其默认值,这里是0。当初始化一个Object数组时,元素默认为

We’ll now see another way giving us the possibility to set values to the array directly when creating it:

现在我们将看到另一种方法,即在创建数组时直接为其设置值。

int[] anArray = new int[] {1, 2, 3, 4, 5};

Here, we initialized a five element array containing numbers 1 to 5. When using this method we don’t need to specify the length of the array, it’s the number of elements then declared between the braces.

在这里,我们初始化了一个包含数字1到5的五元素数组。当使用这种方法时,我们不需要指定数组的长度,它是元素的数量,然后在大括号之间声明。

4. Accessing Elements

4.访问要素

Let’s now see how to access the elements of an array. We can achieve this by requiring an array cell position.

现在让我们看看如何访问一个数组的元素。我们可以通过要求一个数组单元格的位置来实现这一点。

For example, this little code snippet will print 10 to the console:

例如,这个小代码段将打印10到控制台。

anArray[0] = 10;
System.out.println(anArray[0]);

Note how we are using indices to access the array cells. The number between the brackets is the specific position of the array we want to access.

注意我们是如何使用索引来访问数组单元的。括号内的数字是我们要访问的数组的具体位置。

When accessing a cell, if the passed index is negative or goes beyond the last cell, Java will throw an ArrayIndexOutOfBoundException.

当访问一个单元格时,如果传递的索引是负数或超过了最后一个单元格,Java将抛出一个ArrayIndexOutOfBoundException

We should be careful then not to use a negative index, or an index greater than or equal to the array size.

那么我们应该注意不要使用负的索引,或大于或等于数组大小的索引

5. Iterating Over an Array

5.在数组上进行迭代

Accessing elements one by one can be useful, but we might want to iterate through an array. Let’s see how we can achieve this.

一个一个地访问元素可能很有用,但我们可能想在一个数组中进行迭代。让我们看看如何实现这一点。

The first way is to use the for loop:

第一种方法是使用for循环。

int[] anArray = new int[] {1, 2, 3, 4, 5};
for (int i = 0; i < anArray.length; i++) {
    System.out.println(anArray[i]);
}

This should print numbers 1 to 5 to the console. As we can see we made use of the length property. This is a public property giving us the size of the array.

这应该会把数字1到5打印到控制台。我们可以看到,我们使用了length属性。这是一个公有属性,给了我们数组的大小。

Of course, it’s possible to use other loop mechanisms such as while or do while. But, as for Java collections, it’s possible to loop over arrays using the foreach loop:

当然,也可以使用其他循环机制,如whiledo while。但是,对于Java集合来说,可以使用foreach循环来循环数组。

int[] anArray = new int[] {1, 2, 3, 4, 5};
for (int element : anArray) {
    System.out.println(element);
}

This example is equivalent to the previous one, but we got rid of the indices boilerplate code. The foreach loop is an option when:

这个例子等同于前一个例子,但我们去掉了指数的模板代码。foreach循环在以下情况下是一个选项:

  • we don’t need to modify the array (putting another value in an element won’t modify the element in the array)
  • we don’t need the indices to do something else

6. Varargs

6.ǞǞǞ

We’ve already covered the basics when it comes to the creation and manipulation of arrays. Now, we’ll dive into more advanced topics, beginning with varargs. As a reminder, varargs are used to pass an arbitrary number of arguments to a method:

当涉及到创建和操作数组时,我们已经涵盖了基础知识。现在,我们将深入探讨更高级的话题,首先是varargs。作为提醒,varargs用于向一个方法传递任意数量的参数。

void varargsMethod(String... varargs) {}

This method could take from 0 to an arbitrary number of String arguments. An article covering varargs can be found here.

这个方法可以接受从0到任意数量的String参数。关于varargs的文章可以在这里找到。

What we have to know here is that inside the method body, a varargs parameter turns into an array. But, we can also pass an array directly as the argument. Let’s see how by reusing the example method declared above:

我们必须知道的是,在方法主体中,一个varargs参数变成了一个数组。但是,我们也可以直接传递一个数组作为参数。让我们通过重新使用上面声明的例子方法来看看。

String[] anArray = new String[] {"Milk", "Tomato", "Chips"};
varargsMethod(anArray);

Will behave the same as:

将表现得与。

varargsMethod("Milk", "Tomato", "Chips");

7. Transforming an Array into a List

7.将数组转换为列表

Arrays are great, but sometimes it can be handier to deal with List instead. We’ll see here how to transform an array into a List.

数组很好,但有时用List来处理会更方便。我们将在这里看到如何将一个数组转化为List

We’ll first do it the naïve way, by creating an empty list and iterating over the array to add its elements to the list:

我们首先用天真的方式来做,创建一个空列表,然后在数组上迭代,将其元素添加到列表中。

int[] anArray = new int[] {1, 2, 3, 4, 5};

List<Integer> aList = new ArrayList<>();
for (int element : anArray) {
    aList.add(element);
}

But there is another way, a little bit more succinct:

但还有另一种方法,更简洁一点。

Integer[] anArray = new Integer[] {1, 2, 3, 4, 5};
List<Integer> aList = Arrays.asList(anArray);

The static method Arrays.asList takes a varargs argument and creates a list with the passed values. Unfortunately, this method comes with some drawbacks:

静态方法Arrays.asList接收一个varargs参数,并使用传递的值创建一个列表。不幸的是,这个方法有一些缺点。

  • It’s not possible to use an array of primitive types
  • We can’t add or remove elements from the created list, as it’ll throw an UnsupportedOperationException

8. From an Array to a Stream

8.从一个数组到一个流

We can now transform arrays into lists, but since Java 8 we have access to the Stream API and we might want to turn our arrays into Stream. Java provides us with the Arrays.stream method for that:

我们现在可以将数组转化为列表,但是从Java 8开始,我们可以访问Stream API,我们可能想将数组转化为Stream。Java为我们提供了Arrays.stream方法来实现。

String[] anArray = new String[] {"Milk", "Tomato", "Chips"};
Stream<String> aStream = Arrays.stream(anArray);

When passing an Object array to the method it will return a Stream of the matching type (e.g. Stream<Integer> for an array of Integer). When passing a primitive one it will return the corresponding primitive Stream.

当向该方法传递一个Object数组时,它将返回一个匹配类型的Stream(例如,Stream<Integer>用于一个Integer数组)。当传递一个原始的,它将返回相应的原始的Stream

It’s also possible to create the stream only on a subset of the array:

也可以只在数组的一个子集上创建流。

Stream<String> anotherStream = Arrays.stream(anArray, 1, 3);

This will create a Stream<String> with only “Tomato” and “Chips” Strings (the first index being inclusive while the second one is exclusive).

这将创建一个Stream<String>,其中只有 “Tomato “和 “Chips”Strings(第一个索引是包容的,而第二个索引是排他的)。

9. Sorting Arrays

9.数组排序

Let’s now see how to sort an array, that is rearranging its elements in a certain order. The Arrays class provides us with the sort method. A bit like the stream method, sort has a lot of overloadings.

现在让我们看看如何对一个数组进行排序,也就是将其元素按照一定的顺序重新排列。Arrays类为我们提供了sort方法。有点像stream方法,sort有很多的重载方式。

There are overloadings to sort:

有超负荷的工作需要分类。

  • Primitive type arrays: which are sorted in ascending order
  • Object arrays (those Object must implement the Comparable interface): which are sorted according to the natural order (relying on the compareTo method from Comparable)
  • Generic arrays: which are sorted according to a given Comparator

In addition, it’s possible to sort only a specific portion of an array (passing start and end indices to the method).

此外,还可以只对一个数组的特定部分进行排序(向该方法传递开始和结束索引)。

The algorithms behind the sort method are quick sort and merge sort for primitive and other arrays, respectively.

排序方法背后的算法是快速排序合并排序,分别针对原始数组和其他数组。

Let’s see how this all work through some examples:

让我们通过一些例子看看这一切是如何运作的。

int[] anArray = new int[] {5, 2, 1, 4, 8};
Arrays.sort(anArray); // anArray is now {1, 2, 4, 5, 8}

Integer[] anotherArray = new Integer[] {5, 2, 1, 4, 8};
Arrays.sort(anotherArray); // anotherArray is now {1, 2, 4, 5, 8}

String[] yetAnotherArray = new String[] {"A", "E", "Z", "B", "C"};
Arrays.sort(yetAnotherArray, 1, 3, 
  Comparator.comparing(String::toString).reversed()); // yetAnotherArray is now {"A", "Z", "E", "B", "C"}

10. Searching in an Array

10.在一个数组中搜索

Searching an array is pretty simple, we can loop over the array and search our element among the array elements:

搜索一个数组是非常简单的,我们可以在数组上循环,在数组元素中搜索我们的元素。

int[] anArray = new int[] {5, 2, 1, 4, 8};
for (int i = 0; i < anArray.length; i++) {
    if (anArray[i] == 4) {
        System.out.println("Found at index " + i);
        break;
    }
}

Here we searched for number 4 and found it at index 3.

在这里,我们搜索了4号,并在索引3找到了它。

If we have a sorted array though, we can use another solution: the binary search. The principle of binary search is explained in this article.

如果我们有一个排序的数组,我们可以使用另一种解决方案:二进制搜索。二进制搜索的原理在这篇文章中得到了解释。

Fortunately, Java provides us with the Arrays.binarySearch method. We have to give it an array and an element to search.

幸运的是,Java为我们提供了Arrays.binarySearch方法。我们必须给它一个数组和一个要搜索的元素。

In case of a generic array, we also have to give it the Comparator that was used to sort the array in the first place. There is again the possibility to call the method on a subset of the array.

如果是一般的数组,我们还必须给它一个Comparator,这个数组首先是用来排序的。也有可能在数组的一个子集上调用该方法。

Let’s see an example of the binary search method usage:

让我们看看二进制搜索方法的使用实例。

int[] anArray = new int[] {1, 2, 3, 4, 5};
int index = Arrays.binarySearch(anArray, 4);
System.out.println("Found at index " + index);

As we stored number 4 in the fourth cell, this will return index 3 as the result. Note that we used an already sorted array.

由于我们在第四个单元格中存储了数字4,这将返回索引3作为结果。请注意,我们使用了一个已经排序的数组。

11. Concatenating Arrays

11.连接数组

Finally, let’s see how to concatenate two arrays. The idea is to create an array which length is the sum of the two arrays to concatenate. After that we have to add the elements of the first one and then the elements of the second one:

最后,让我们看看如何将两个数组连接起来。我们的想法是创建一个数组,其长度为要连接的两个数组之和。之后,我们必须添加第一个数组的元素,然后再添加第二个数组的元素

int[] anArray = new int[] {5, 2, 1, 4, 8};
int[] anotherArray = new int[] {10, 4, 9, 11, 2};

int[] resultArray = new int[anArray.length + anotherArray.length];
for (int i = 0; i < resultArray.length; i++) {
    resultArray[i] = (i < anArray.length ? anArray[i] : anotherArray[i - anArray.length]);
}

As we can see, when the index is still lesser than the first array length we add elements from that array. Then we add elements from the second one. We can make use of the Arrays.setAll method to avoid writing a loop:

我们可以看到,当索引仍然小于第一个数组的长度时,我们从该数组中添加元素。然后我们再从第二个数组中添加元素。我们可以利用Arrays.setAll方法来避免写一个循环。

int[] anArray = new int[] {5, 2, 1, 4, 8};
int[] anotherArray = new int[] {10, 4, 9, 11, 2};

int[] resultArray = new int[anArray.length + anotherArray.length];
Arrays.setAll(resultArray, i -> (i < anArray.length ? anArray[i] : anotherArray[i - anArray.length]));

This method will set all array element according to the given function. This function associates an index with a result.

该方法将根据给定的函数设置所有数组元素。该函数将一个索引与一个结果联系起来。

Here is a third option to merge to arrays: System.arraycopy. This method takes a source array, a source position, a destination array, a destination position and an int defining the number of elements to copy:

这里有第三个选项,可以合并到数组。System.arraycopy。这个方法需要一个源数组,一个源位置,一个目标数组,一个目标位置和一个int,定义要复制的元素数量。

System.arraycopy(anArray, 0, resultArray, 0, anArray.length);
System.arraycopy(anotherArray, 0, resultArray, anArray.length, anotherArray.length);

As we can see, we copy the first array, then the second (after the last element of the first one).

我们可以看到,我们复制了第一个数组,然后是第二个数组(在第一个数组的最后一个元素之后)。

12. Conclusion

12.结语

In this detailed article we’ve covered basic and some advanced usages of arrays in Java.

在这篇详细的文章中,我们已经介绍了Java中数组的基本和一些高级用法。

We saw that Java offers a lot of methods to deal with arrays through the Arrays utility class. There also are utility classes to manipulate arrays in libraries such as Apache Commons or Guava.

我们看到,Java通过Arrays实用类提供了很多处理数组的方法。在Apache CommonsGuava等库中也有处理数组的实用类。

The full code for this article can be found on our GitHub.

这篇文章的完整代码可以在我们的GitHub上找到。