24.md 9.5 KB
Newer Older
W
init  
wizardforcel 已提交
1 2 3 4
# 数组

> 原文: [https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html)

W
wizardforcel 已提交
5
*数组*是一个容器对象,它包含固定数量的单一类型的值。创建数组时,将建立数组的长度。创建后,其长度是固定的。您已经在“Hello World!”的`main`方法中看到了一个数组示例。应用。本节更详细地讨论了数组。
W
init  
wizardforcel 已提交
6

W
wizardforcel 已提交
7
![Illustration of an array as 10 boxes numbered 0 through 9; an index of 0 indicates the first element in the array](img/1c76b8eadfd68779ef8986ab2bca7e3b.jpg)
W
init  
wizardforcel 已提交
8 9 10

10 个元素的数组。

W
wizardforcel 已提交
11

W
init  
wizardforcel 已提交
12

W
wizardforcel 已提交
13
数组中的每个项称为*元素*,每个元素由其数字*索引*访问。如上图所示,编号从 0 开始。例如,第 9 个元素将在索引 8 处访问。
W
init  
wizardforcel 已提交
14 15 16

以下程序 [`ArrayDemo`](examples/ArrayDemo.java) 创建一个整数数组,将一些值放入数组中,并将每个值打印到标准输出。

W
wizardforcel 已提交
17
```java
W
init  
wizardforcel 已提交
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
class ArrayDemo {
    public static void main(String[] args) {
        // declares an array of integers
        int[] anArray;

        // allocates memory for 10 integers
        anArray = new int[10];

        // initialize first element
        anArray[0] = 100;
        // initialize second element
        anArray[1] = 200;
        // and so forth
        anArray[2] = 300;
        anArray[3] = 400;
        anArray[4] = 500;
        anArray[5] = 600;
        anArray[6] = 700;
        anArray[7] = 800;
        anArray[8] = 900;
        anArray[9] = 1000;

        System.out.println("Element at index 0: "
                           + anArray[0]);
        System.out.println("Element at index 1: "
                           + anArray[1]);
        System.out.println("Element at index 2: "
                           + anArray[2]);
        System.out.println("Element at index 3: "
                           + anArray[3]);
        System.out.println("Element at index 4: "
                           + anArray[4]);
        System.out.println("Element at index 5: "
                           + anArray[5]);
        System.out.println("Element at index 6: "
                           + anArray[6]);
        System.out.println("Element at index 7: "
                           + anArray[7]);
        System.out.println("Element at index 8: "
                           + anArray[8]);
        System.out.println("Element at index 9: "
                           + anArray[9]);
    }
} 

```

该程序的输出是:

W
wizardforcel 已提交
67
```java
W
init  
wizardforcel 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80
Element at index 0: 100
Element at index 1: 200
Element at index 2: 300
Element at index 3: 400
Element at index 4: 500
Element at index 5: 600
Element at index 6: 700
Element at index 7: 800
Element at index 8: 900
Element at index 9: 1000

```

W
wizardforcel 已提交
81
在实际编程情况下,您可能会使用受支持的*循环结构之一*来迭代数组的每个元素,而不是像前面的示例中那样单独写入每一行。但是,该示例清楚地说明了数组语法。您将了解[控制流程](flow.html)部分中的各种循环结构(`for``while``do-while`)。
W
init  
wizardforcel 已提交
82 83 84 85 86

## 声明变量以引用数组

前面的程序使用以下代码行声明一个数组(名为`anArray`):

W
wizardforcel 已提交
87
```java
W
init  
wizardforcel 已提交
88 89 90 91 92
// declares an array of integers
int[] anArray;

```

W
wizardforcel 已提交
93
与其他类型的变量的声明一样,数组声明有两个组件:数组的类型和数组的名称。数组的类型写为`_ 类型 _ []` ,其中`_ 类型 _`是包含元素的数据类型;括号是特殊符号,表示此变量包含数组。数组的大小不是其类型的一部分(这就是括号为空的原因)。数组的名称可以是您想要的任何名称,前提是它遵循先前在[命名](variables.html#naming)部分中讨论的规则和约定。与其他类型的变量一样,声明实际上并不创建数组;它只是告诉编译器该变量将包含指定类型的数组。
W
init  
wizardforcel 已提交
94 95 96

同样,您可以声明其他类型的数组:

W
wizardforcel 已提交
97
```java
W
init  
wizardforcel 已提交
98 99 100 101 102 103 104 105 106 107 108 109 110
byte[] anArrayOfBytes;
short[] anArrayOfShorts;
long[] anArrayOfLongs;
float[] anArrayOfFloats;
double[] anArrayOfDoubles;
boolean[] anArrayOfBooleans;
char[] anArrayOfChars;
String[] anArrayOfStrings;

```

您还可以将括号放在数组名称后面:

W
wizardforcel 已提交
111
```java
W
init  
wizardforcel 已提交
112 113 114 115 116 117 118 119 120 121 122
// this form is discouraged
float anArrayOfFloats[];

```

但是,公约不鼓励这种形式;括号标识数组类型,并应显示类型名称。

## 创建,初始化和访问数组

创建数组的一种方法是使用`new`运算符。 `ArrayDemo`程序中的下一个语句为 10 个整数元素分配一个具有足够内存的数组,并将该数组分配给`anArray`变量。

W
wizardforcel 已提交
123
```java
W
init  
wizardforcel 已提交
124 125 126 127 128 129 130
// create an array of integers
anArray = new int[10];

```

如果缺少此语句,则编译器会输出如下错误,并且编译失败:

W
wizardforcel 已提交
131
```java
W
init  
wizardforcel 已提交
132 133 134 135 136 137
ArrayDemo.java:4: Variable anArray may not have been initialized.

```

接下来的几行为数组的每个元素赋值:

W
wizardforcel 已提交
138
```java
W
init  
wizardforcel 已提交
139 140 141 142 143 144 145 146
anArray[0] = 100; // initialize first element
anArray[1] = 200; // initialize second element
anArray[2] = 300; // and so forth

```

每个数组元素都通过其数字索引访问:

W
wizardforcel 已提交
147
```java
W
init  
wizardforcel 已提交
148 149 150 151 152 153 154 155
System.out.println("Element 1 at index 0: " + anArray[0]);
System.out.println("Element 2 at index 1: " + anArray[1]);
System.out.println("Element 3 at index 2: " + anArray[2]);

```

或者,您可以使用快捷语法来创建和初始化数组:

W
wizardforcel 已提交
156
```java
W
init  
wizardforcel 已提交
157 158 159 160 161 162 163 164 165 166
int[] anArray = { 
    100, 200, 300,
    400, 500, 600, 
    700, 800, 900, 1000
};

```

这里数组的长度由大括号之间提供的值的数量确定,并用逗号分隔。

W
wizardforcel 已提交
167
您还可以使用两组或更多组括号声明数组数组(也称为*多维*数组),例如`String[][] names`。因此,每个元素必须由相应数量的索引值访问。
W
init  
wizardforcel 已提交
168 169 170

在 Java 编程语言中,多维数组是一个数组,其组件本身就是数组。这与 C 或 Fortran 中的数组不同。这样做的结果是允许行的长度不同,如下面的 [`MultiDimArrayDemo`](examples/MultiDimArrayDemo.java) 程序所示:

W
wizardforcel 已提交
171
```java
W
init  
wizardforcel 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
class MultiDimArrayDemo {
    public static void main(String[] args) {
        String[][] names = {
            {"Mr. ", "Mrs. ", "Ms. "},
            {"Smith", "Jones"}
        };
        // Mr. Smith
        System.out.println(names[0][0] + names[1][0]);
        // Ms. Jones
        System.out.println(names[0][2] + names[1][1]);
    }
}

```

该程序的输出是:

W
wizardforcel 已提交
189
```java
W
init  
wizardforcel 已提交
190 191 192 193 194 195 196
Mr. Smith
Ms. Jones

```

最后,您可以使用内置的`length`属性来确定任何数组的大小。以下代码将数组的大小打印到标准输出:

W
wizardforcel 已提交
197
```java
W
init  
wizardforcel 已提交
198 199 200 201 202 203 204 205
 System.out.println(anArray.length);

```

## 复制数组

`System`类有一个`arraycopy`方法,可以用来有效地将数据从一个数组复制到另一个数组:

W
wizardforcel 已提交
206
```java
W
init  
wizardforcel 已提交
207 208 209 210 211
public static void arraycopy(Object src, int srcPos,
                             Object dest, int destPos, int length)

```

W
wizardforcel 已提交
212
两个`Object`参数指定要从复制*的数组和将*复制到*的数组。三个`int`参数指定源数组中的起始位置,目标数组中的起始位置以及要复制的数组元素的数量。_
W
init  
wizardforcel 已提交
213 214 215

以下程序 [`ArrayCopyDemo`](examples/ArrayCopyDemo.java) 声明了一系列`char`元素,拼写单词“decafffeinated”。它使用`System.arraycopy`方法将数组组件的子序列复制到第二个数组中:

W
wizardforcel 已提交
216
```java
W
init  
wizardforcel 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
class ArrayCopyDemo {
    public static void main(String[] args) {
        char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e',
			    'i', 'n', 'a', 't', 'e', 'd' };
        char[] copyTo = new char[7];

        System.arraycopy(copyFrom, 2, copyTo, 0, 7);
        System.out.println(new String(copyTo));
    }
}

```

该程序的输出是:

W
wizardforcel 已提交
232
```java
W
init  
wizardforcel 已提交
233 234 235 236 237 238 239 240 241 242
caffein

```

## 数组操作

数组是编程中使用的强大而有用的概念。 Java SE 提供了执行与数组相关的一些最常见操作的方法。例如, [`ArrayCopyDemo`](examples/ArrayCopyDemo.java) 示例使用`System`类的`arraycopy`方法,而不是手动迭代源数组的元素并将每个元素放入目标数组。这是在幕后执行的,使开发人员只使用一行代码来调用该方法。

为方便起见,Java SE 提供了几种在 [`java.util.Arrays`](https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html) 类中执行数组操作(常见任务,如复制,排序和搜索数组)的方法。例如,可以修改前一个示例以使用`java.util.Arrays`类的`copyOfRange`方法,如 [`ArrayCopyOfDemo`](examples/ArrayCopyOfDemo.java) 示例中所示。区别在于使用`copyOfRange`方法不需要在调用方法之前创建目标数组,因为方法返回目标数组:

W
wizardforcel 已提交
243
```java
W
init  
wizardforcel 已提交
244 245 246 247 248 249 250 251 252 253 254 255 256 257
class ArrayCopyOfDemo {
    public static void main(String[] args) {

        char[] copyFrom = {'d', 'e', 'c', 'a', 'f', 'f', 'e',
            'i', 'n', 'a', 't', 'e', 'd'};

        char[] copyTo = java.util.Arrays.copyOfRange(copyFrom, 2, 9);

        System.out.println(new String(copyTo));
    }
}

```

W
wizardforcel 已提交
258
如您所见,此程序的输出相同(`caffein`),尽管它需要较少的代码行。请注意,`copyOfRange`方法的第二个参数是要复制的范围的初始索引,包括,而第三个参数是要复制的范围的最终索引,*专用*。在此示例中,要复制的范围不包括索引 9 处的数组元素(其中包含字符`a`)。
W
init  
wizardforcel 已提交
259 260 261 262 263 264 265

`java.util.Arrays`类中的方法提供的一些其他有用的操作是:

*   在数组中搜索特定值以获取其所在的索引(`binarySearch`方法)。
*   比较两个数组以确定它们是否相等(`equals`方法)。
*   填充数组以在每个索引处放置特定值(`fill`方法)。
*   按升序对数组进行排序。这可以使用`sort`方法顺序完成,也可以使用 Java SE 8 中引入的`parallelSort`方法同时完成。多处理器系统上的大型数组的并行排序比顺序数组排序更快。