Slicing Arrays in Java – 在Java中对数组进行切分

最后修改: 2022年 11月 5日

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

1. Overview

1.概述

We know that Java’s List has the subList() method, which allows us to slice the source List object. However, there’s no standard subArray() method on the array side.

我们知道Java的ListsubList()方法,它允许我们对源List对象进行切片。然而,在数组方面没有标准的subArray()方法。

In this tutorial, let’s explore how to get a subarray of a given array in Java.

在本教程中,让我们探讨如何在Java中获得一个给定数组的子数组。

2. Introduction to the Problem

2.对问题的介绍

As usual, let’s understand the problem through an example. Let’s say we have a string array:

像往常一样,让我们通过一个例子来理解这个问题。比方说,我们有一个字符串数组。

String[] LANGUAGES = new String[] { "Python", "Java", "Kotlin", "Scala", "Ruby", "Go", "Rust" };

As we can see, the LANGUAGES array holds some programming language names. Also, since applications written in “Java”, “Kotlin”, or “Scala” can run on the Java Virtual Machine, let’s say we’d like a subarray containing these three elements. In other words, we want to get from the second to the fourth element (index 1, 2, 3) from the LANGUAGES array:

我们可以看到,LANGUAGES数组保存了一些编程语言名称。另外,由于用“Java”、”Kotlin”“Scala”编写的应用程序可以在Java虚拟机上运行,假设我们想要一个包含这三个元素的子数组。换句话说,我们想从LANGUAGES数组中获得第二到第四个元素(索引123):

String[] JVM_LANGUAGES = new String[] { "Java", "Kotlin", "Scala" };

In this tutorial, we’ll address different approaches to solving this problem. Further, for simplicity, we’ll use unit test assertions to verify if each solution works as expected.

在本教程中,我们将讨论解决这个问题的不同方法。此外,为了简单起见,我们将使用单元测试断言来验证每个解决方案是否按预期工作。

Next, let’s see them in action.

接下来,让我们看看他们的行动。

3. Using the Stream API

3.使用流API

A significant new feature Java 8 brought us is the Stream API. So if the Java version we’re working with is 8 or later, we can slice a given array using the Stream API.

Java 8给我们带来的一个重要的新特性是Stream API。因此,如果我们使用的Java版本是8或更高的版本,我们就可以使用Stream API对一个给定的数组进行切片。

First, we can convert an array to a Stream object using the Arrays.stream() method. We should note that we should use the Arrays.stream() method with three arguments:

首先,我们可以使用Arrays.stream()方法将一个数组转换为Stream对象我们应该注意,我们应该使用带有三个参数的Arrays.stream()方法。

  • the array – in this example, it’s LANGUAGES
  • startInclusive – the start index to extract from the array above, inclusive
  • endExclusive – the end index to extract, as the name implies, exclusive

Therefore, to solve our problem, we can pass LANGUAGES, 1, and 4 to the Arrays.stream() method.

因此,为了解决我们的问题,我们可以将LANGUAGES, 1,4传递给Arrays.stream()方法。

Next, let’s create a test to see if it can get our desired subarray:

接下来,让我们创建一个测试,看看它是否能得到我们想要的子阵列。

String[] result = Arrays.stream(LANGUAGES, 1, 4).toArray(String[]::new);
assertArrayEquals(JVM_LANGUAGES, result);

As the code above shows, after we convert the array to a Stream, we can call the toArray() method to convert it back to an array.

正如上面的代码所示,在我们将数组转换为Stream之后,我们可以调用toArray()方法,将其转换为数组。

If we run the test, it passes. Therefore, it does the job.

如果我们运行这个测试,它就会通过。因此,它完成了工作。

4. Using the Arrays.copyOfRange() Method

4.使用Arrays.copyOfRange()方法

We’ve learned to use the Stream API to solve the problem. However, the Stream API is only available in Java 8 and later.

我们已经学会使用Stream API来解决这个问题。然而,Stream API只在Java 8及以后的版本中可用

If our Java version is 6 or later, we can solve the problem using the Arrays.copyOfRange() method. This method’s arguments are similar to the Arrays.stream() method – the array, the from-index (inclusive), and the to-index (exclusive).

如果我们的Java版本是6或更高,我们可以使用Arrays.copyOfRange()方法来解决这个问题。这个方法的参数与Arrays.stream()方法类似–数组、from-index(包括)和to-index(exclusive)。

So next, let’s create a test to see if Arrays.copyOfRange() can solve the problem:

所以接下来,让我们创建一个测试,看看Arrays.copyOfRange()是否能解决这个问题。

String[] result = Arrays.copyOfRange(LANGUAGES, 1, 4);
assertArrayEquals(JVM_LANGUAGES, result);

The test passes if we give it a run. So it solves our problem as well.

如果我们让它运行一下,测试就会通过。所以它也解决了我们的问题。

5. Using the System.arraycopy() Method

5.使用System.arraycopy()方法

The Arrays.copyOfRange() approach solves the problem by copying a part of the given array to a new array.

Arrays.copyOfRange()方法通过将给定数组的一部分复制到一个新的数组来解决问题。

When we want to copy a part from an array, apart from the Arrays.copyOfRange() method, we can also use the System.arraycopy() method. So next, let’s solve the problem using this method.

当我们想从一个数组中复制一个部分时,除了使用Arrays.copyOfRange()方法外,我们还可以使用System.arraycopy()方法。那么接下来,我们就用这个方法来解决问题吧。

We’ve seen the Arrays.copyOfRange() returns the result subarray. However, the System.arraycopy() method’s return type is void. Therefore, we must create a new array object and pass it to the arraycopy() method. The method fills the copied elements in the array:

我们已经看到Arrays.copyOfRange()返回结果子数组。然而,System.arraycopy()方法的返回类型是void。因此,我们必须创建一个新的数组对象并将其传递给arraycopy()方法。该方法将复制的元素填充到数组中。

String[] result = new String[3];
System.arraycopy(LANGUAGES, 1, result, 0, 3);
assertArrayEquals(JVM_LANGUAGES, result);

The test passes if we run it.

如果我们运行它,测试就会通过。

As we can see in the code above, the arraycopy() method has five parameters. Let’s understand what they mean:

正如我们在上面的代码中看到的,arraycopy()方法有五个参数。让我们来理解它们的含义。

  • the source array – LANGUAGE
  • the from index in the source array to copy – 1
  • the target array to hold the copied result – result
  • the start index in the target array to store the copied result – 0
  • the number of elements we want to copy from the source array – 3

It’s worth mentioning that if the result array contains data already, the arraycopy() method may overwrite the data:

值得一提的是,如果结果数组已经包含数据,arraycopy()方法可能会覆盖这些数据

String[] result2 = new String[] { "value one", "value two", "value three", "value four", "value five", "value six", "value seven" };
System.arraycopy(LANGUAGES, 1, result2, 2, 3);
assertArrayEquals(new String[] { "value one", "value two", "Java", "Kotlin", "Scala", "value six", "value seven" }, result2);

This time, the result2 array contains seven elements. Further, when we call the arraycopy() method, we tell it to fill the copied data from index 2 in result2. As we can see, the copied three elements have overwritten the original elements in result2.

这一次,result2数组包含七个元素。此外,当我们调用arraycopy()方法时,我们告诉它从result2中的索引2填充复制的数据。我们可以看到,复制的三个元素已经覆盖了result2中的原始元素。

Also, we should note that System.arraycopy() is a native method, and the Arrays.copyOfRange() method invokes System.arraycopy() internally.

另外,我们应该注意,System.arraycopy()是一个本地方法,Arrays.copyOfRange()方法在内部调用了System.arraycopy()

6. Using ArrayUtils From the Apache Commons Lang3 Library

6.使用Apache Commons Lang3库的ArrayUtils

Apache Commons Lang3 is a pretty widely used library. Its ArrayUtils provides a lot of handy methods so that we can work with arrays easier.

Apache Commons Lang3是一个使用相当广泛的库。它的ArrayUtils提供了很多方便的方法,使我们可以更容易地处理数组。

Finally, let’s solve the problem using the ArrayUtils class.

最后,让我们用ArrayUtils类来解决这个问题。

Before we start using ArrayUtils, let’s add the dependency to our Maven configuration:

在我们开始使用ArrayUtils之前,让我们在Maven配置中添加该依赖项。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

Of course, we can always find the latest version in the Maven central repository.

当然,我们可以随时在Maven中央仓库找到最新版本

The ArrayUtils class has the subarray() method, which allows us to get a subarray quickly:

ArrayUtils类有subarray()方法,它允许我们快速获得一个子数。

String[] result = ArrayUtils.subarray(LANGUAGES, 1, 4);
assertArrayEquals(JVM_LANGUAGES, result);

As we can see, it’s pretty straightforward to solve the problem using the subarray() method.

我们可以看到,使用subarray()方法来解决这个问题是非常直接的。

7. Conclusion

7.结语

In this article, we’ve learned different approaches to getting a subarray from a given array.

在这篇文章中,我们已经学习了从一个给定的数组中获取子数组的不同方法。

As usual, all code snippets presented here are available over on GitHub.

像往常一样,这里介绍的所有代码片段都可以在GitHub上找到