章
目
录
学习在Java中使用不同的方法拆分数组。我们将学习将数组分成相等的部分,在指定的索引处以及相等的长度。
1.使用Arrays.copyOfRange() API
copyOfRange()
方法创建一个与原始数组相同类型的新数组,并将原始数组指定范围内的项复制到新数组中。请注意,该方法在内部使用System.arraycopy()
来复制数组项。
public static T[] copyOfRange(T[] original, int from, int to)
以下是该方法的参数:
- original – 要复制范围的原始数组
- from – 要复制范围的起始索引,包括此索引
- to – 要复制范围的最终索引,不包括此索引(此索引可能超出数组范围)
需要注意的重要一点是,to索引可能超出数组的长度。这种索引位置将被填充为数组类型的默认值。
例如,对于int
、long
和double
类型,额外的索引位置将填充为零。对于布尔数组,这些索引位置将填充为false
,对于对象数组,这些位置将填充为null
。
如果from
大于to
,它将抛出IllegalArgumentException
异常。
2.在指定的索引处拆分数组
假设我们要以一种方式分割数组,以便我们应该得到两个具有定义长度的数组。在这种情况下,我们必须使用copyOfRange()
API从原始数组创建两个新数组。
第一个新数组将包含从零开始到指定索引处的项,而第二个新数组将包含从指定索引到原始数组末尾的项。
int[] original = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int givenIndex = 3;
splitArrayPart1 = Arrays.copyOfRange(original, 0, givenIndex);
splitArrayPart2 = Arrays.copyOfRange(original, givenIndex, original.length);
System.out.println(Arrays.toString(splitArrayPart1)); //[0, 1, 2]
System.out.println(Arrays.toString(splitArrayPart2)); //[3, 4, 5, 6, 7, 8, 9]
3.将数组分成两等份
将数组分成两半非常类似于第一个示例。我们只需要自己找到分割位置,即数组的中间位置。
int[] original = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int splitSize = original.length / 2;
int[] splitArrayPart1 = Arrays.copyOfRange(original, 0, splitSize);
int[] splitArrayPart2 = Arrays.copyOfRange(original, splitSize, original.length);
System.out.println(Arrays.toString(splitArrayPart1)); //[0, 1, 2, 3, 4]
System.out.println(Arrays.toString(splitArrayPart2)); //[5, 6, 7, 8, 9]
4.将数组分成N份
这有点复杂,在这里,我们必须迭代数组长度,但按指定数量的块进行迭代。然后,我们必须使用copyOfRange()方
法从那些复制的项创建新的数组实例。
如果在平均分割数组后还有剩余的项,我们必须特别注意。我们需要创建一个新数组来存储这些剩余项。
例如,我们的原始数组包含10个项。如果我们尝试以这样的方式分割数组,以便任何新数组都不包含超过3个项。在这种情况下,分割过程后将会有4个数组。前三个数组每个都有3个项,而第四个数组只有一个项。
以下是执行上述所有工作的方法。
public static <T extends Object> List<T[]> splitArray(T[] array, int splitSize) {
int numberOfArrays = array.length / splitSize;
int remainder = array.length % splitSize;
int start = 0;
int end = 0;
List<T[]> list = new ArrayList<T[]>();
for (int i = 0; i < numberOfArrays; i++) {
end += splitSize;
list.add(Arrays.copyOfRange(array, start, end));
start = end;
}
if(remainder > 0) {
list.add(Arrays.copyOfRange(array, start, (start + remainder)));
}
return list;
}
让我们使用我们原始的数组来测试这种方法,并分割成每个数组中最多只能有3个项。
List<Integer[]> arrayParts = splitArray(ArrayUtils.toObject(original), 3);
for(Integer[] o: arrayParts) {
System.out.println(Arrays.toString(o));
}
//Output
[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9]
5.结论
在本教程中,我们学习了在Java中针对不同用途拆分数组的方法。我们学会了使用Arrays.copyOfRange()
API来将数组拆分成任意数量的部分。
还有其他方法可以用于数组拆分,例如将数组转换为列表,然后再拆分列表。这些方法会创建不必要的临时变量,而没有明显的优势。
6.扩展
其实如果不是数组,而是List集合,我们可以借助com.google.guava
包中的Lists.partition()
这个api来实现,可以参考文章:《Java使用Lists.partition指定长度拆分List集合》
即使是数组,我们也可以先将数组转List,分割后再分别转数组,也算是一种曲线救国的实现方式了。