Java数组
Java数组是相同类型的变量的集合。例如," int"数组是" int"类型变量的集合。数组中的变量是有序的,每个变量都有一个索引。在本文后面的内容中,我们将看到如何索引到数组中。这是Java数组的说明:
在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实例化数组
声明Java数组变量时,仅声明数组本身的变量(引用)。该声明实际上并不创建数组。我们创建一个像这样的数组:
int[] intArray; intArray = new int[10];
这个例子创建了一个类型为int的数组,里面有10个int变量的空间。
前面的Java数组示例创建了一个`int'数组,它是一种原始数据类型。我们还可以创建对象引用的数组。例如:
String[] stringArray = new String[10];
Java允许我们创建对任何类型的对象(对任何类的实例)的引用的数组。
Java数组文字
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数组长度无法更改
创建阵列后,无法调整其大小。在某些编程语言(例如JavaScript)中,数组可以在创建后更改其大小,但是在Java中,数组一旦创建就无法更改其大小。如果我们需要一个可以改变其大小的类似数组的数据结构,则应该使用一个List,或者可以创建可调整大小的Java数组。在某些情况下,我们还可以使用Java RingBuffer,顺便说一下,它是在内部使用Java数组实现的。
访问Java数组元素
Java数组中的每个变量也称为"元素"。因此,前面显示的示例创建了一个数组,该数组的空间可以容纳10个元素,每个元素都是" int"类型的变量。
数组中的每个元素都有一个索引(一个数字)。我们可以通过其索引访问数组中的每个元素。这是一个例子:
intArray[0] = 0; int firstInt = intArray[0];
这个例子首先设置索引为0的元素(int)的值,然后将索引为0的元素的值读入int变量。
我们可以像使用普通变量一样使用Java数组中的元素。我们可以读取它们的值,为其分配值,在计算中使用元素并将特定元素作为参数传递给方法调用。
Java数组中元素的索引始终以0开头,并继续到数组大小以下的数字1. 因此,在上面的示例中,该数组具有10个元素,索引从0到9.
阵列长度
我们可以通过数组的长度字段访问数组的长度。这是一个例子:
int[] intArray = new int[10]; int arrayLength = intArray.length;
在此示例中,名为" arrayLength"的变量在第二行代码执行后将包含值10.
迭代数组
我们可以使用Java for循环遍历数组的所有元素。这是在Java中使用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"循环中的第一个循环遍历" String"数组,创建" String",并使单元格引用该" String"。
两个" for"循环中的第二个循环遍历" String"数组,并打印出单元格引用的所有字符串。
如果这是一个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"具有不同的值。
我们也可以使用Java中的" 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); }
多维Java数组
上面显示的示例全部创建了一个具有单一维的数组,这意味着索引从0到向上的元素。但是,可以创建一个数组,其中每个元素具有两个或者多个索引,以在数组中标识(定位)该元素。
通过在Java中创建多维数组,可以为每个要添加的维添加一组方括号([]
)。这是一个创建二维数组的示例:
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];
执行完最后一行Java代码后,名为" oneInt"的变量将包含值129.
迭代多维数组
在Java中迭代多维数组时,需要分别迭代数组的每个维。这是在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); } }
将元素插入数组
有时我们需要将元素插入Java数组中的某个位置。这是将新值插入Java数组中的方法:
int[] ints = new int[20]; int insertIndex = 10; int newValue = 123; //move elements below insertion point. for(int i=ints.length-1; i > insertIndex; i--){ ints[i] = ints[i-1]; } //insert new value ints[insertIndex] = newValue; System.out.println(Arrays.toString(ints));
该示例首先创建一个数组。然后,它定义一个插入索引和一个要插入的新值。然后,从插入索引到数组末尾的所有元素都将在数组中向下移动一个索引。请注意,这会将数组中的最后一个值移出数组(将被删除)。
上面的数组插入代码可以嵌入Java方法中。看起来是这样的:
public void insertIntoArray( int[] array, int insertIndex, int newValue){ //move elements below insertion point. for(int i=array.length-1; i > insertIndex; i--){ array[i] = array[i-1]; } //insert new value array[insertIndex] = newValue; }
该方法将一个" int []"数组作为参数,以及插入新值和新值的索引。我们可以通过如下调用此方法将元素插入数组:
int[] ints = new int[20]; insertIntoArray(ints, 0, 10); insertIntoArray(ints, 1, 23); insertIntoArray(ints, 9, 67);
当然,如果" insertIntoArray()"方法与上述代码位于不同的类中,则需要该类的对象才能调用该方法。或者,如果" insertIntoArray()"方法是"静态"方法,则需要在方法名称前放置类名和一个点。
从阵列中删除元素
有时我们需要从Java数组中删除一个元素。以下是在Java中从数组中删除元素的代码:
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方法中。这是这种删除数组的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()
方法是static
,则需要在方法名称前放置类名和点。
在数组中查找最小值和最大值
有时我们可能需要在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"可以采用的最大可能值。这样做是为了确保初始值不小于数组中的最小值。
其次,示例遍历数组并将每个值与" minValue"进行比较。如果数组中的元素小于" 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.
找到最小值的主要区别是maxVal的初始化以及maxVal与数组元素的比较。
数组类
Java包含一个特殊的实用程序类,它使我们可以更轻松地执行许多常用的数组操作,例如,对数组进行复制和排序,填充数据,在数组中搜索等。该实用程序类称为"数组",位于标准Java包中java.util
。因此,该类的完全限定名称为:
java.util.Arrays
在以下各节中,我将介绍该类中的一些方法。请记住,为了在Java类中使用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中的另一个数组中。
通过迭代数组来复制数组
在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(0到数组的长度减去1)的值初始化源数组。第三,将源数组中的每个元素复制到目标数组中。
使用Arrays.copyOf()复制数组
复制Java数组的第二种方法是使用Arrays.copyOf()方法。这是使用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()方法复制一个数组的范围,而不必复制整个数组。这是在Java中使用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个参数。第一个参数是要复制的数组。第二个参数是源数组中要包含在副本中的第一个索引。第三个参数是源数组中要包含在副本中的最后一个索引(不包括在内,因此传递10将复制直到包含索引9为止)。
使用Arrays.toString()将数组转换为字符串
我们可以使用Arrays.toString()方法将基本类型的Java数组转换为字符串。这是一个如何使用arrays.toString()将int数组转换为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()方法对数组的元素进行排序。对数组元素进行排序会根据元素的排序顺序重新排列元素的顺序。这是一个" 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的int
数组;
for循环遍历数组并将值插入每个元素。插入的值将按降序从10到1.
在" for"循环之后,使用" Arrays.toString()"将数组转换为" String",并输出到控制台(命令行)。此时,写入控制台的输出(数组的" String"版本)如下所示:
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
然后使用" Arrays.sort()"对数组进行排序。现在将按升序对元素进行排序。
对数组进行排序后,再次将其转换为String
并打印到控制台。这次打印的输出看起来像这样:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
排序对象数组
前面显示的" Arrays.sort()"示例仅适用于原始数据类型的Java数组。 Java的原始数据类型具有自然顺序,既可以是数字顺序,也可以是ASCII表中字符的顺序(表示字符的二进制数字)。
如果要对对象数组进行排序,则需要使用其他方法。对象可能没有任何自然的排序顺序,因此我们需要提供另一个能够确定对象顺序的对象。这样的对象称为"比较器"。
比较器是一个接口。在我有关Java接口的教程中介绍了接口。我的Java Collections教程中有关Java Collections Sorting教程的文本中将更详细地介绍"比较器"接口。如果我们不理解Java接口或者"比较器"接口,可能会很难理解以下代码。但是我还是会给你看。
首先是我们要排序的对象的类:
private static class Employee{ public String name; public int employeeId; public Employee(String name, int employeeId){ this.name = name; this.employeeId = employeeId; } }
雇员类是雇员的简单模型(我已经创建了雇员类)。员工有一个姓名和一个员工ID。我们可以按名称或者员工ID对" Employee"对象的数组进行排序。我将向我们展示如何做到这两个。
这是第一个使用" 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数组,以及一个Comparator实现,该实现可以确定Employee对象的顺序。如果我们不完全理解此声明,请不要担心。它创建了Comparator接口的匿名实现。接口的匿名实现在我有关Java嵌套类的文章中进行了介绍。该实现还使用Java泛型,这可能进一步使其难以阅读。
在此示例中要抓住的重要一点是Comparator接口的匿名内部实现的compare()方法的实现。如果第一个对象比第二个对象"更大"(排序顺序晚),则此方法返回正数;如果第一个对象比"第二个对象"更大(排序顺序),则此方法返回负数;如果第一个对象"更小",则返回负数(排序顺序早于第二个对象。在上面的示例中,我们只需要调用String.compare()方法即可为我们进行比较(比较员工姓名)。
对数组进行排序后,我们将对其进行遍历并打印出员工姓名。这是输出的输出外观:
Anna John Xander
请注意,与最初将其插入数组的顺序相比,该顺序如何反转。
现在让我们看一下如何按"雇员"对象的雇员ID对"雇员"对象进行排序。这是之前的示例,它具有对Comparator接口的匿名实现的compare()方法的修改实现:
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()
方法可以使用给定值填充数组。这比遍历数组并自己插入值要容易得多。这是一个使用" Arrays.fill()"来填充" int"数组的示例:
int[] intArray = new int[10]; Arrays.fill(intArray, 123); System.out.println(Arrays.toString(intArray));
本示例创建一个" int"数组,并将值123填充到数组中的所有元素中。该示例的最后一行将数组转换为String
并将其输出到控制台。输出结果如下所示:
[123, 123, 123, 123, 123, 123, 123, 123, 123, 123]
Arrays.fill()方法有一个版本,该版本采用from和to索引,因此只有在此间隔内具有索引的元素才会填充给定值。这是该" Arrays.fill()"方法的示例:
int[] intArray = new int[10]; Arrays.fill(ints2, 3, 5, 123) ; System.out.println(Arrays.toString(intArray));
此示例仅使用索引123填充索引3和4(3到5,不包含5)的元素。这是此示例输出的输出:
0, 0, 0, 123, 123, 0, 0, 0, 0, 0]
使用Arrays.binarySearch()搜索数组
Arrays类包含一组称为BinarySearch()的方法。此方法可在数组中执行二进制搜索。必须首先对数组进行排序。我们可以自己执行此操作,也可以通过本文前面介绍的" Arrays.sort()"方法执行此操作。这是一个" Arrays.binarySearch()"示例:
int[] ints = {0,2,4,6,8,10}; int index = Arrays.binarySearch(ints, 6); System.out.println(index);
此示例的第二行在数组中搜索值6. BinarySearch()方法将返回其中找到元素的数组中的索引。在上面的示例中,binarySearch()方法将返回3.
如果数组中存在多个具有搜索值的元素,则不能保证将找到哪个元素。
如果找不到具有给定值的元素,则将返回负数。负数是将插入要搜索的元素的索引,然后减一。看这个例子:
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);
本示例在数组中搜索值2,但仅在索引0和4之间(不包含4)进行搜索。
除了没有找到匹配元素的情况外,此版本的binarySearch()的工作方式与其他版本相同。如果没有发现在索引间隔内匹配的元素,则binarySearch()
仍将返回应其中插入值的索引。但是,如果间隔中的所有值都小于所需的值,则binarySearch()
将返回-toIndex -1而不是-array length 1.
int[] ints = {0,2,4,6,8,10}; int index = Arrays.binarySearch(ints, 0, 4, 12);
将返回-5,而不是-7,就像binarySearch(ints,12)
一样。
使用Arrays.equals()检查数组是否相等
" java.util.Arrays"类包含一组称为" equals()"的方法,可用于检查两个Java数组是否相等。如果两个数组的长度相同,并且两个元素按照在数组中找到的顺序彼此相等,则认为两个数组相等。看一下这个" Arrays.equals()"示例:
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"进行比较。第一次比较将得出值" true",因为" ints1"和" ints2"包含相同顺序的相同元素。第二次比较将得出值" false"。数组" ints1"包含与" ints3"相同的元素,但顺序不同。因此,两个数组不视为相等。
通过反射访问数组
可以通过Java Reflection访问数组。在本教程中,我已经介绍了有关使用Java Reflection访问数组的内容。