Java数组

数组是相同类型变量的集合。例如,一个int数组是int类型的变量的集合。数组中的变量是有序的,每个变量都有一个索引。你将在篇教程后面看到如何使用索引。以下是Java数组的示例:

声明一个数组

Java数组变量的声明就像声明变量一样,除此外还需要在类型之后添加[]。以下是一个简单的Java数组声明示例:

int[] intArray;

你可以像使用其他变量一样将Java数组用作字段,静态字段,局部变量或参数。数组只是数据类型的变体。它不是单个变量,而是一种类型的变量的集合。

下面是更多的Java数组示例:

String[]  stringArray;

MyClass[] myClassArray;

上例中第一行声明了一个 String类型的数组。第二行声明了一个自定义类型对象 MyClass的数组。

在Java中声明数组时,实际上方括号[]的位置可以选择。通过上面的例子,你已经看到的第一个可以放置的位置。就是放在数据类型的后面(例如String [])。而第二个可以放置的位置是在在变量名后面。以下Java数组声明都是有效的:

int[] intArray;
int   intArray[];

String[] stringArray;
String   stringArray[];

MyClass[] myClassArray;
MyClass   myClassArray[];

就个人而言,我更喜欢在数据类型(例如String [])之后放置方括号[],而不是在变量名之后。毕竟,数组是一种特殊的数据类型,所以我觉得在数据类型后面放置方括号会使代码的可读性更高。

实例化数组

当你声明一个Java数组变量时,你只是声明该变量(引用)给数组本身。该声明实际上并不会创建一个数组。你可以像下面这样创建一个数组:

int[] intArray;

intArray = new int[10];

上面例子中,创建了一个 int类型数组,并且数组有10个 int变量空间。

一旦创建了一个数组,它的大小就不能被改变。在某些语言中,数组可以在创建之后改变它们的大小,但是在Java中,数组一旦创建就不能改变它的大小。如果你需要一个类似数组,并且可以在创建后改变它的大小的数据结构的话,你可以使用List。

前面的Java数组示例创建了一个int类型数组。你也可以创建一个对象引用的数组。例如:

String[] stringArray = new String[10];

Java可以允许创建任何类型对象(任何类的实例)的引用数组。

数组字面量

Java编程语言包含一个实例化基本类型和字符串类型数组的快捷方式。如果你事先知道插入到数组中的值,则可以使用数组字面量。示例如下:

int[]   ints2 = new int[]{ 1,2,3,4,5,6,7,8,9,10 };

注意在{...}块内列出的是要插入到数组中的值。这个列表的长度也决定了该数组的长度。

实际上,你可以在最新版本的Java中省略 new int[]部门。示例如下:

int[]   ints2 = { 1,2,3,4,5,6,7,8,9,10 };

在大括号内的值,被称为数组字面量。

这种代码书写风格适用于所有基本类型的数组,也适用于字符串数组。示例如下:

String[] strings = {"one", "two", "three"};

访问数组中元素

Java数组中的每个变量也称为“元素”。因此,前面的示例创建了一个包含10个元素的数组,每个元素都是一个int类型的变量。

数组中的每个元素都有一个索引(一个数字)。你可以通过索引访问数组中的每个元素。示例如下:

intArray[0] = 0;

int firstInt = intArray[0];

本例子中首先给数组中索引为0的元素赋值为0,然后再将数组中索引为0的元素值读取出来。

你可以像使用普通变量一样使用Java数组中的元素。你可以读取它们的值,为它们赋值,在计算中使用这些元素,还可以将其中某个元素作为参数传递给方法使用。

Java数组中元素的索引总是从0开始,直到数组大小-1为止。因此,上面带有10个元素的数组中,索引是从0到9。

数组长度

你可以通过数组的 length字段获取到数组的长度。示例如下:

int[] intArray = new int[10];

int arrayLength = intArray.length;

在本例中,执行完代码后,变量 arrayLength值为10。

数组迭代

你可以使用for循环遍历数组的所有元素。示例如下:

String[] stringArray = new String[10];

for(int i=0; i < stringArray.length; i++) {
    stringArray[i] = "String no " + i;
}

for(int i=0; i < stringArray.length; i++) {
    System.out.println( stringArray[i] );
}

本例中,首先创建一个 String类型的引用数组。当你创建了一个对象引用数组时,数组中的每个元素都指向null - 没有对象。

第一个for循环遍历字符串数组,同时每次创建一个字符串,并让元素引用该字符串。

第二个for循环遍历字符串数组,并打印出每个元素引用的所有字符串。

如果这是一个int(基本类型)类型的数组,它可能会像下面这样:

int[] intArray = new int[10];

for(int i=0; i < intArray.length; i++) {
    intArray[i] = i;
}

for(int i=0; i < intArray.length; i++) {
    System.out.println( intArray[i] );
}

变量i被初始化为0,直到数组的长度减1为止。在这个例子中,i取值是0到9,每次在for循环中重复执行一次代码,每次迭代i都有一个不同的值。

你也可以通过 "for-each"来迭代一个数组。示例如下:

int[] intArray = new int[10];

for(int theInt : intArray) {
    System.out.println(theInt);
}

for-each循环让你可以访问数组中的每个元素,但是不会提供每个元素索引的信息。此外,你也只能访问该值,而不能改变元素的值。如果你需要更改元素的值,就需要使用正常的for循环,如前所示。

for-each循环也适用于对象数组。下面的示例,展示了如何迭代一个String对象的数组:

String[] stringArray = {"one", "two", "three"};

for(String theString : stringArray) {
    System.out.println(theString);
}

多维数组

上面的例子都创建了具有单个维度的数组,意味着元素的的索引从0往上递增。但是,我们也可以创建一种数组,其中每个元素都有两个或多个索引,可以在数组中识别(定位)它。

你可以通过在方括号[]后面添加任意的数量的方括号来创建一个多维数组。下面例子创建了二维数组:

int[][] intArray = new int[10][20];

本例中,创建了一个 int类型的二维数组。该数组第一维中包含10个元素,在第二维中包含20个元素。换句话说,这个例子创建了一个 int类型数组的数组。该数组的数组有10个int数组的空间,每个int数组都有20个int元素的空间。

你可以使用每个维度的一个索引访问多维数组中的元素。在上面的例子中,你将使用两个索引来访问该数组元素。示例如下:

int[][] intArray = new int[10][20];

intArray[0][2] = 129;

int oneInt = intArray[0][2];

在以上代码执行后,变量 oneInt中值为129。

多维数组迭代

在Java中迭代多维数组时,需要分别迭代数组的每个维度。多维数组迭代示例如下:

int[][] intArray = new int[10][20];

for(int i=0; i < intArrays.length; i++){
    for(int j=0; j < intArrays[i].length; j++){
        System.out.println("i: " + i + ", j: " + j);
    }
}

插入元素到数组中

有时你需要将元素插入到某个数组中。以下是向数组中插入新值的方法:

int[] ints   = new int[20];

int insertIndex = 10;
int newValue    = 123;

//逐个向后移动在插入点后的元素
for(int i=ints.length-1; i > insertIndex; i--){
    ints[i] = ints[i-1];
}

//插入新值
ints[insertIndex] = newValue;

System.out.println(Arrays.toString(ints));

该示例首先创建一个数组。然后定义了一个插入索引和一个新的插入值。然后,从插入点索引到数组末尾的所有元素,并将它们逐个移动到下一个索引。请注意,这会将数组中的最后一个值移出数组(它将被简单地删除)。

上面的数组插入代码可以嵌入到Java方法中。就像下面这样:

public void insertIntoArray(
        int[] array, int insertIndex, int newValue){

    //逐个向后移动在插入点后的元素
    for(int i=array.length-1; i > insertIndex; i--){
        array[i] = array[i-1];
    }

    //插入新值
    array[insertIndex] = newValue;
}

这个方法接受一个 int[]数组作为参数,以及插入新值的索引和新值。你可以通过调用该方法来将元素插入到数组中:

int[] ints   = new int[20];

insertIntoArray(ints, 0, 10);
insertIntoArray(ints, 1, 23);
insertIntoArray(ints, 9, 67);

当然,如果insertIntoArray()方法与上述代码不在同一类中,就需要创建一个该类的对象来调用该方法。或者,如果insertIntoArray()方法是静态的,就需要将类名加上".insertIntoArray()"来调用该方法。

从数组中移除元素

有时你可能想要从数组中移除一个元素,可以参考以下示例:

int[] ints   = new int[20];

ints[10] = 123;

int removeIndex = 10;

for(int i = removeIndex; i < ints.length -1; i++){
    ints[i] = ints[i + 1];
}

本例中,首先创建一个int数组。然后它将索引为10的元素的值设置为123.然后,该示例将删除索引为10的元素。通过将索引为10后面的所有元素向前移动一个位置,将元素移除。删除后,数组中的最后一个元素将保存两次——倒数两个元素都是一样的。

上面的代码可以嵌入到Java方法如下所示:

public void removeFromArray(
    int[] array, int removeIndex){

    for(int i = removeIndex; i < array.length -1; i++){
        array[i] = array[i + 1];
    }
}

这个removeFromArray()方法有两个参数:需要删除元素的数组,以及要删除元素的索引。

当然,如果removeFromArray()方法与上述代码不在同一类中,就需要创建一个该类的对象来调用该方法。或者,如果removeFromArray()方法是静态的,就需要将类名加上".removeFromArray()"来调用该方法。

求数组中的最小、最大值

有时你可能需要在Java数组中找到最小值或最大值。 Java没有任何内置函数来查找数组中的最小值和最大值,但是我会告诉你如何自己编写代码来实现。

首先我们来找到数组中的最小值:

int[] ints = {0,2,4,6,8,10};

int minVal = Integer.MAX_VALUE;

for(int i=0; i < ints.length; i++){
    if(ints[i] < minVal){
        minVal = ints[i];
    }
}

System.out.println("minVal = " + minVal);

该示例首先将 minVal设置为 Integer.MAX_VALUE,这是 int可以表示的最大可能值。这样做是为了确保初始值不小心小于数组中的最小值。

其次,该示例遍历数组并将每个值与minVal进行比较。如果数组中的元素小于minVal,则将minVal设置为元素的值。

最后打印出数组中找到的最小值。在上面的例子中,最小值是0。

下面是求数组最大值的代码,与找最小值类似:

int[] ints = {0,2,4,6,8,10};

int maxVal = Integer.MIN_VALUE;
for(int i=0; i < ints.length; i++){
    if(ints[i] > maxVal){
        maxVal = ints[i];
    }
}
System.out.println("maxVal = " + maxVal);

上例中,会打印最大值10。

Arrays类

Java包含一个特殊的实用程序类,让你可以更轻松地执行许多常用的数组操作,如复制和排序数组,填充数据,搜索数组等。实用程序类称为 Arrays,它位于标准Java包java.util中。因此,该类的完全限定名称是:

java.util.Arrays

我将在下面的章节中介绍这个类中的几个方法。记住,如果你想在Java类中使用java.util.Arrays,必须先导入它。示例如下:

package myjavaapp;

import java.util.Arrays;

public class MyClass{

    public static void main(String[] args) {

    }
}

注意import java.util.Arrays就是将java.util.Arrays类导入到Java类中的语句。

复制数组

你可以通过几种方式来复制数组。

通过迭代来复制

在Java中复制数组的第一种方法是遍历数组,并将源数组的每个值复制到目标数组中。下面是使用该方法复制数组的方法:

int[] source = new int[10];
int[] dest   = new int[10];

for(int i=0; i < source.length; i++) {
    source[i] = i;
}

for(int i=0; i < source.length; i++) {
    dest[i] = source[i];
}

首先创建了两个 int数组。其次,源数组的初始值从0到9。第三步,将源数组中的每个元素被复制到目标数组中。

使用Arrays.copyOf()方法

第二种复制Java数组的方法是使用Arrays.copyOf()方法。示例如下:

int[] source = new int[10];

for(int i=0; i < source.length; i++) {
    source[i] = i;
}

int[] dest = Arrays.copyOf(source, source.length);

Arrays.copyOf()方法需要2个参数。第一个参数是要复制的数组。第二个参数是新数组的长度。此参数可用于指定要复制的源数组中元素个数。

使用Arrays.copyOfRange()复制

复制Java数组的第三种方法是使用Arrays.copyOfRange()方法。 Arrays.copyOfRange()方法可以复制一个数组指定的范围,不一定是完整的数组。示例如下:

int[] source = new int[10];

for(int i=0; i < source.length; i++) {
    source[i] = i;
}

int[] dest = Arrays.copyOfRange(source, 0, source.length);

Arrays.copyOfRange()方法需要3个参数。第一个参数是要复制的数组。第二个参数是要复制的数组范围的开始索引。第三个参数是要复制的数组范围的结尾索引。

通过Arrays.toString()将数组转换成String

你可以使用Arrays.toString()方法将原始类型的Java数组转换为String。示例如下:

int[]   ints = new int[10];

for(int i=0; i < ints.length; i++){
    ints[i] = 10 - i;
}

System.out.println(java.util.Arrays.toString(ints));

第一行创建了一个10元素的 int数组。for循环将数组中元素分别从10~1进行初始化。最后一行打印出Arrays.toString()的返回值。结果如下:

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

数组排序

你可以使用Arrays.sort()方法对数组中的元素进行排序。对数组元素进行排时序会根据顺序重新排列元素的顺序。示例如下:

int[]   ints = new int[10];

for(int i=0; i < ints.length; i++){
    ints[i] = 10 - i;
}

System.out.println(java.util.Arrays.toString(ints));

java.util.Arrays.sort(ints);

System.out.println(java.util.Arrays.toString(ints));

第一行代码声明了包含10个元素的整型数组。

for循环从10~1初始化数组元素的值。此时,数组中元素值是按照10~1降序排列的。

在for循环之后,使用Arrays.toString()将数组转换为字符串,并将其输出到控制台(命令行)。此时,控制台的输出(数组的字符串版本)如下所示:

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

然后该数组使用Arrays.sort()进行排序。数组中的元素现在将按升序排列。

对数组进行排序后,再次将其转换为字符串并打印到控制台。这次打印的输出如下所示:

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

对象数组的排序

前面使用的Arrays.sort()方法仅适用于基本数据类型的Java数组。 Java的原始数据类型要么具有自然顺序,要么具有数字顺序,要么具有ASCII表中的字符顺序(代表字符的二进制数字)。

如果你想对一个对象数组进行排序,就需要使用不同的方法。对象可能没有任何自然排序顺序,所以你需要提供另一个能够确定对象顺序的对象,这种对象称为比较器。

比较器是一个接口。有关Java接口的内容请参看后续章节。更多关于比较器的接口请参看Java集合教程。如果你不了解Java接口或比较器接口,你可能会比较难理解下面的代码。但无论如何,我会向你展示它。

下面是我们想要排序的类:

private static class Employee{
    public String name;
    public int    employeeId;

    public Employee(String name, int employeeId){
        this.name       = name;
        this.employeeId = employeeId;
    }
}

Employee类是一个简单的员工模型。员工有一个名字和一个员工ID。你可能按名称或其员工ID排序对其进行排序。我会告诉你如何实现

首先使用Arrays.sort()方法按照名字对Employee对象数组进行排序:

Employee[] employeeArray = new Employee[3];

employeeArray[0] = new Employee("Xander", 1);
employeeArray[1] = new Employee("John"  , 3);
employeeArray[2] = new Employee("Anna"  , 2);

java.util.Arrays.sort(employeeArray, new Comparator<Employee>() {
    @Override
    public int compare(Employee e1, Employee e2) {
        return e1.name.compareTo(e2.name);
    }
});


for(int i=0; i < employeeArray.length; i++) {
    System.out.println(employeeArray[i].name);
}

首先声明一个Java数组。该数组的类型是我之前创建的Employee类。其次,创建三个Employee对象并将其插入到数组中。

然后,调用Arrays.sort()方法对数组进行排序。作为Arrays.sort()方法的参数,我们传递了employee数组和一个实现了Employee对象排序的比较器。如果你不完全理解这个说法,也不用担心。这其中还是用匿名方式实现了该比较器接口。同时还使用了Java泛型的知识。这些都会在后面章节讲解。

在这个例子中重要的是比较器接口的匿名接口的compare()方法的实现。如果第一个对象比第二个对象“更大”,则返回一个正数;如果第一个对象是“更小”,则返回一个负数;如果它们是“相等的”,则返回0。在上面的例子中,我们只需调String.compare()方法,然后该方法会自动比较员工姓名大小。

排序后,我们遍历数组并打印出员工的名字。输出如下:

Anna
John
Xander

请注意,与最初插入数组的顺序相比,现在是如何排序的。

现在让我们看看如何通过员工ID来对Employee对象进行排序。示例代码如下:

Employee[] employeeArray = new Employee[3];

employeeArray[0] = new Employee("Xander", 1);
employeeArray[1] = new Employee("John"  , 3);
employeeArray[2] = new Employee("Anna"  , 2);

java.util.Arrays.sort(employeeArray, new Comparator<Employee>() {
    @Override
    public int compare(Employee e1, Employee e2) {
        return e1.employeeId - e2.employeeId;
    }
});

for(int i=0; i < employeeArray.length; i++) {
    System.out.println(employeeArray[i].name);
}

请注意compare()方法如何通过用一个员工id减去另一个员工id所返回的不同值来确定顺序的。这是确定数字变量顺序最简单的方法。

输出结果如下:

Xander
Anna
John

如果要先比较Employee对象的名字,如果相同,再比较员工id的话,compare()方法实现如下:

java.util.Arrays.sort(employeeArray, new Comparator<Employee>() {
    @Override
    public int compare(Employee e1, Employee e2) {
        int nameDiff = e1.name.compareTo(e2.name);
        if(nameDiff != 0) { return nameDiff; }

        return e1.employeeId - e2.employeeId;
    }
});

使用Arrays.fill()方法填充数组

Arrays类有一组名为fill()的方法。Arrays.fill()方法可以用给定的值填充数组。这要比遍历数组并自己插入值更容易。示例如下:

int[] intArray = new int[10];

Arrays.fill(intArray, 123);

System.out.println(Arrays.toString(intArray));

此示例创建一个int数组,并将值123填充到数组中的所有元素。该示例的最后一行将数组转换为一个字符串,并将其打印到控制台。输出如下:

[123, 123, 123, 123, 123, 123, 123, 123, 123, 123]

Arrays.fill()方法有一个版本可以使用起始索引和结束索引,所以只有在这个索引范围内的元素才会被填充给定的值。示例如下:

int[] intArray = new int[10];

Arrays.fill(intArray, 3, 5, 123) ;

System.out.println(Arrays.toString(intArray));

这个例子只填充索引3和索引4(索引3到索引5,不包含索引5)的值为123。输出如下:

[0, 0, 0, 123, 123, 0, 0, 0, 0, 0]

使用Arrays.binarySearch()搜索数组

Arrays类包含一组称为binarySearch()的方法。此方法可以帮助你在数组中执行二进制搜索。该数组必须先排序。你可以自己写排序方法,或者通过本文前面介绍的Arrays.sort()方法实现。示例如下:

int[] ints = {0,2,4,6,8,10};

int index = Arrays.binarySearch(ints, 6);

System.out.println(index);

此示例的第二行是在数组中搜索6. binarySearch()方法将返回找到该元素在数组中的索引。在上面的例子中,binarySearch()方法将返回3。

如果数组中有多个元素与搜索值一样,这种情况不能保证会找到哪个元素。

如果找不到具有给定值的元素,则返回负数。负数将是插入搜索元素的索引减1。示例如下:

int[] ints = {0,2,4,6,8,10};

int index = Arrays.binarySearch(ints, 7);

System.out.println(index);

在数组中找不到数字7。如果要在数组中插入7(并保留排序顺序),则数字7应该已经插入索引4的数组中。因此binarySearch()返回-4 - 1 = -5。

如果数组中的所有元素都小于查找值,则binarySearch()将返回-数组的长度- 1.示例如下:

int[] ints = {0,2,4,6,8,10};

int index = Arrays.binarySearch(ints, 12);

System.out.println(index);

在这个例子中,我们在数组中搜索12,但是数组中的所有元素都小于12.因此binarySearch()将返回-length(-6)-1 = -6 -1 = -7。

Arrays.binarySearch()方法也存在只搜索数组一部分的版本。示例如下:

int[] ints = {0,2,4,6,8,10};

int index = Arrays.binarySearch(ints, 0, 4, 2);

System.out.println(index);

此示例在数组中索引0到4之间(不包括索引4)搜索值2。

这种情况下的binarySearch()工作方式与其他版本一样,只是在找不到匹配元素的情况下会有所不同。如果在索引间隔内找不到匹配的元素,那么binarySearch()仍然会返回值应该插入的索引。但是,如果间隔中的所有值都小于查找值,则binarySearch()将返回-截至索引 -1,而不是-数组长度-1。示例如下:

int[] ints = {0,2,4,6,8,10};

int index = Arrays.binarySearch(ints, 0, 4, 12);

此例中,会返回-5而不是-7;

通过Arrays.equals()方法判断数组是否相等

java.util.Arrays类包含一组名为equals()的方法,可用于检查两个Java数组是否相等。当两个数组长度相等并且数组元素相应位置对应相等,则认为两数组相等。示例如下:

int[] ints1 = {0,2,4,6,8,10};
int[] ints2 = {0,2,4,6,8,10};
int[] ints3 = {10,8,6,4,2,0};

boolean ints1EqualsInts2 = Arrays.equals(ints1, ints2);
boolean ints1EqualsInts3 = Arrays.equals(ints1, ints3);

System.out.println(ints1EqualsInts2);
System.out.println(ints1EqualsInts3);

此示例将数组ints1分别与数组ints2和ints3进行比较。第一次比较返回值为真,因为ints1和ints2包含相同顺序的相同元素。第二个比较返回值为假。数组ints1与ints3包含相同的元素,但顺序不同。所以这两个数组并不相同。

通过反射器来访问数组

可以通过Java Reflection访问数组。详细内容参考相关章节。

下一篇:Java字符串

results matching ""

    No results matching ""