|
|
|
|
数组的定义和使用大多和C是一样的。数组是存放一类数据的一种数据结构。Java中的数组(Array)是一种特殊的对象(通过类实例化),也有特殊的语法结构。在学习Array的时候,请注意其语法,以及与后续类和对象的区别。
|
|
|
|
|
|
|
|
|
|
## 1. 声明与使用
|
|
|
|
|
|
|
|
|
|
### 1.1. 声明与使用数组
|
|
|
|
|
|
|
|
|
|
下面这个例子说明了数组的基本使用。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class ArrayTest {
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
int[] myList;
|
|
|
|
|
|
|
|
|
|
myList = new int[2];
|
|
|
|
|
myList[0] = 0;
|
|
|
|
|
myList[1] = 1;
|
|
|
|
|
|
|
|
|
|
System.out.println(myList[1]);
|
|
|
|
|
|
|
|
|
|
myList = new int[3];
|
|
|
|
|
|
|
|
|
|
System.out.println(myList[1]);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Java中数组的声明与使用与C类似,`int[] myList` 定义了一个可以存放int数据类型的数组,但是此时还没有为这个数组分配内存。这一点和C的指针类是,其实myList这个变量叫做引用变量,也和指针类似。
|
|
|
|
|
|
|
|
|
|
要为myList这个数组分配内存,使用 `new int[2]` 这种类似的语法。该语法返回一个数组对象的引用地址,数组的容量是2,并赋值给引用变量 myList,然后就可以通过引用变量 myList对数组进行操作了。
|
|
|
|
|
|
|
|
|
|
可以重复对一个数组引用变量使用new语句分配内存,例如,例子中第6行和第12行。与C不同的是,Java不用对动态分配的内存进行回收。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**特别注意这里new的语法结构,后面是数组定义时的类型,大小设置不是圆括号,而是方括号!**
|
|
|
|
|
|
|
|
|
|
### 1.2. 声明和分配内存在一行中
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class ArrayTest2 {
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
int[] myList = new int[2];
|
|
|
|
|
|
|
|
|
|
myList[0] = 0;
|
|
|
|
|
myList[1] = 1;
|
|
|
|
|
|
|
|
|
|
System.out.println(myList[1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 1.3. 在声明的同时初始化数组
|
|
|
|
|
|
|
|
|
|
这个语法结构和C类似:
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class ArrayTest3 {
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
int[] myList = {1,3,5,7};
|
|
|
|
|
System.out.println(myList[1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**注意,大括号赋初值的语法只能在数组声明中使用,不能单独使用。**
|
|
|
|
|
|
|
|
|
|
### 1.4. 数组元素的缺省值
|
|
|
|
|
|
|
|
|
|
When an array is created, its elements are assigned the default value of
|
|
|
|
|
|
|
|
|
|
0 for the numeric primitive data types,
|
|
|
|
|
'\u0000' for char types, and
|
|
|
|
|
false for boolean types.
|
|
|
|
|
|
|
|
|
|
## 2. 数组操作
|
|
|
|
|
|
|
|
|
|
### 2.1. 数组对象上的操作
|
|
|
|
|
|
|
|
|
|
数组本质上是一个对象,因此直接可以在数组的引用变量上对数组进行操作。例如,取得数组的长度:
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class ArrayTest2 {
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
int[] myList = {1,3,5,7};
|
|
|
|
|
System.out.println(myList.length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
myList 作为一个对象,还有很多实例函数,只需要在IDE中写入这个引用变量,并在后面打一个点,就会出现这个对象的所有操作(可能包括变量、函数和常量)。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
有兴趣的可以研究一下这些函数的作用,其实从这些函数名就可以知道大约的作用。
|
|
|
|
|
|
|
|
|
|
### 2.2. 数组元素的初始值
|
|
|
|
|
|
|
|
|
|
When an array is created, its elements are assigned the default value of
|
|
|
|
|
|
|
|
|
|
0 for the numeric primitive data types,
|
|
|
|
|
'\u0000' for char types, and
|
|
|
|
|
false for boolean types.
|
|
|
|
|
|
|
|
|
|
### 2.3. 加强的for循环
|
|
|
|
|
|
|
|
|
|
和C一样,Java数组的下标也是从0开始的;结合数组的长度,可以对数组进行遍历。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class Test {
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
int arrayInt[] = { 1, 3, 5, 7 };
|
|
|
|
|
for (int i = 0; i < arrayInt.length; i++) {
|
|
|
|
|
System.out.println(arrayInt[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Java还提供了一种更方便的for循环:
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class ArrayTest2 {
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
int[] myList = { 1, 3, 5, 7 };
|
|
|
|
|
for (int i : myList) {
|
|
|
|
|
System.out.println(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
这个加强版的for循环例子如上,myList是一个数组(更准确的说是一个数据集),每次取得一个数据集的元素并保存在变量i中(注意这个临时变量i的类型必须和数组中存放数据的类型一致),直到所有的元素被遍历。
|
|
|
|
|
|
|
|
|
|
**注意,这个for循环在以后会大量用到。**
|
|
|
|
|
|
|
|
|
|
### 2.4. 数组变量是引用变量(指针)
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
对数组赋值,会改变引用变量的内存指向,这和C的指针是一个概念。
|
|
|
|
|
|
|
|
|
|
**注意:Java中不存在手动回收内存,不存在指针悬空的情况。**
|
|
|
|
|
|
|
|
|
|
### 2.5. 使用函数来复制数组
|
|
|
|
|
|
|
|
|
|
可以使用循环来复制数组:
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class Test {
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
int[] sourceArray = { 2, 3, 1, 5, 10 };
|
|
|
|
|
int[] targetArray = new int[sourceArray.length];
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < sourceArray.length; i++)
|
|
|
|
|
targetArray[i] = sourceArray[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Java在System这个类中提供了一个更加通用的数组复制函数`arraycopy`,注意这个函数是静态函数。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class ArrayTest2 {
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
int[] myList1 = { 1, 3, 5, 7 };
|
|
|
|
|
int[] myList2 = new int[10];
|
|
|
|
|
System.arraycopy(myList1, 0, myList2, 0, 3);
|
|
|
|
|
for (int i : myList2) {
|
|
|
|
|
System.out.println(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
注意 System.arraycopy 这个函数的参数代表什么意思。
|
|
|
|
|
|
|
|
|
|
### 2.6. 数组作为函数参数
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class ArrayTest3 {
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
int[] iA = { 5, 6, 7, 8 };
|
|
|
|
|
System.out.println("The original array:");
|
|
|
|
|
printArray(iA);
|
|
|
|
|
|
|
|
|
|
changeVal(iA);
|
|
|
|
|
System.out.println("After change item value in function:");
|
|
|
|
|
printArray(iA);
|
|
|
|
|
|
|
|
|
|
changeArray(iA);
|
|
|
|
|
System.out.println("After change array in function:");
|
|
|
|
|
printArray(iA);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void printArray(int[] a) {
|
|
|
|
|
for (int i : a) {
|
|
|
|
|
System.out.println(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void changeVal(int[] a) {
|
|
|
|
|
for (int i = 0; i < a.length; i++) {
|
|
|
|
|
a[i] = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void changeArray(int[] a) {
|
|
|
|
|
a = new int[3];
|
|
|
|
|
for (int i = 0; i < a.length; i++) {
|
|
|
|
|
a[i] = i + 100;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**注意:可以在函数中改变数组内部元素的值。**
|
|
|
|
|
|
|
|
|
|
### 2.7. 对数组元素排序
|
|
|
|
|
|
|
|
|
|
Arrys这个类中提供对数组进行排序的函数:
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class Test {
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
|
|
|
|
|
double[] numbers = { 6.0, 4.4, 1.9, 2.9, 3.4, 3.5 };
|
|
|
|
|
java.util.Arrays.sort(numbers);
|
|
|
|
|
for (double item : numbers)
|
|
|
|
|
System.out.print(item + " ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
排序后,数组中的元素按照从小到达排列。
|
|
|
|
|
|
|
|
|
|
### 2.8. 数组元素的查找
|
|
|
|
|
|
|
|
|
|
我们可以使用循环来查找数组中某个元素的位置,其实Java已经给我们提供了一个数组查找的函数`binarySearch`。注意这里的binary是指二分法排序,而不是指二进制。如果采用二分法查找,那么数组必须是有序的。如果无法确保数组是有序的,使用前面的`java.util.Arrays.sort`函数先对数组进行排序。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class Test {
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
int[] list = { 2, 4, 7, 10, 11, 45, 50, 59, 60, 66, 69, 70, 79 };
|
|
|
|
|
int pos = -1;
|
|
|
|
|
pos = java.util.Arrays.binarySearch(list, 11);
|
|
|
|
|
System.out.println("Index is " + pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
这个函数就是binarySearch,这个函数指使用注意这个函数的使用,前面的一窜`java.util.Arrays` 不是都指类的名字;最有最后的 `Arrays` 是类名,而 `java.util` 是命名空间。通常情况下,可以简单的理解命名空间就是目录的层级关系。
|
|
|
|
|
|
|
|
|
|
关于`java.util.Arrays`这个类还有很多其他函数,可以在IDE中通过输入点(.)查看:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
有兴趣的同学可以自己去研究一下。
|
|
|
|
|
|
|
|
|
|
### 2.9. 补充
|
|
|
|
|
|
|
|
|
|
这些内容可能考试不会直接考到,但是会方便你的编程,希望你们可以掌握。
|
|
|
|
|
|
|
|
|
|
关于String的操作,通常会用到把一个字符串转换成数组。例如一个以空格分隔的字符串,我们希望把每一段切取出来,形成一个数组,这时我们使用:
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
String string = "AAA BBB CCC";
|
|
|
|
|
string.split(" ");
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
split的参数是一个正则表达式(这个我们可以不用掌握),这里如果字符串是空格分隔,写入一个空格的字符串就可以了,标识拆分的字符串。
|
|
|
|
|
|
|
|
|
|
函数返回是一个 String\[\] 类型的数组,你得到的是 {"AAA", "BBB", "CCC" } ,注意,不包含分隔字符串。
|
|
|
|
|
|
|
|
|
|
相对的,可以使用 join 函数把一个字符串数组以一定的分隔符连接成一个新的字符串。
|
|
|
|
|
|
|
|
|
|
split 是实例函数,join是静态函数。
|
|
|
|
|
|
|
|
|
|
## 3. 读取命令行参数
|
|
|
|
|
|
|
|
|
|
细心的同学们可能注意到了,在主函数中有一个字符串的数组,这个是做什么的?其实这是传递程序运行是输入的命令行参数设计的,我们看看下面这个例子:
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class Calculator {
|
|
|
|
|
/** Main method */
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
// Check number of strings passed
|
|
|
|
|
if (args.length != 3) {
|
|
|
|
|
System.out.println("Usage: java Calculator operand1 operator operand2");
|
|
|
|
|
System.exit(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The result of the operation
|
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
|
|
// Determine the operator
|
|
|
|
|
switch (args[1].charAt(0)) {
|
|
|
|
|
case '+':
|
|
|
|
|
result = Integer.parseInt(args[0]) + Integer.parseInt(args[2]);
|
|
|
|
|
break;
|
|
|
|
|
case '-':
|
|
|
|
|
result = Integer.parseInt(args[0]) - Integer.parseInt(args[2]);
|
|
|
|
|
break;
|
|
|
|
|
case '.':
|
|
|
|
|
result = Integer.parseInt(args[0]) * Integer.parseInt(args[2]);
|
|
|
|
|
break;
|
|
|
|
|
case '/':
|
|
|
|
|
result = Integer.parseInt(args[0]) / Integer.parseInt(args[2]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Display result
|
|
|
|
|
System.out.println(args[0] + ' ' + args[1] + ' ' + args[2] + " = " + result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
主函数`void main(String[] args)` 中有有一个args 的字符串数组。编译这个程序,然后在命令行下执行,如果不记得命令行中如何编译和运行java,请参考第一章中的内容。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
在命令行中运行编译好的代码 `java Calculator 1 + 21` 其中 java是指虚拟机,后面的 `Calculator` 是Java编译后的可执行代码;`1 + 21` 是命令行参数。这个参数会传递给Calculator的主程序,通过main函数的args这个字符串数组解析出来。如同Scanner 对象一样,解析这个数组是按照空格区分的,因此,这个例子中我们得到的args数组是:
|
|
|
|
|
|
|
|
|
|
| 数组元素 | 值 | 说明 |
|
|
|
|
|
| ------- | --- | --- |
|
|
|
|
|
| args[0] | 1 | |
|
|
|
|
|
| args[1] | + | |
|
|
|
|
|
| args[2] | 21 | |
|
|
|
|
|
|
|
|
|
|
后面的代码就很简单了。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 4. 本章重点
|
|
|
|
|
|
|
|
|
|
1. 掌握数组的申明和使用;
|
|
|
|
|
2. 掌握增强for循环的使用;
|
|
|
|
|
3. 理解数组作为函数参数的使用;
|
|
|
|
|
4. 其他内容均为了解。
|