数组是一种数据结构,用来存储同一类型值的集合。通过一个整型下标可以访问数组中的每一个值。
声明数组:
int[] a; // 声明
int a[]; // 声明
int[] a = new int[100]; // 声明并初始化可以存储 100 个整数的数组
int[] a = {2, 3, 5, 7, 11}; // 创建数组并赋予初始值
int[] a = new int[] {17, 19, 23, 29, 31, 37}; // 与上面一样
int[] a = new int[0]; // 创建一个长度为 0 的数组。注意,与 null 的区别
double[][] a = new double[10][10]; // 二维数组
int[][] a = { // 二维数组初始化
{16, 3, 2, 13},
{5, 10, 11, 8},
{9, 6, 7, 12},
{4, 15, 14, 1},
};
int[][] a = new int[10][]; // 创建一个具有行数的数组
创建一个数组时,如果没有指定值。数字数组都初始化为 0 ;boolean 数组都初始化为 false;对象数组都初始化为 null。表示这些数组的元素还未存放任何值。
一旦创建了数组,就不能再改变它的大小(尽管可以改变每一个数组元素)。
Java 中有一个增强型 for 循环,可以不必关注下标值(当然,如果要用到下标值还是得用传统的 for 循环):
for(int element : a)
其中 a 必须是一个数组或者是一个实现了 Iterable 接口的类对象(例如 ArrayList )。
数组拷贝
在 Java 中,可以直接将一个数组变量拷贝给另一个变量。这时,两个变量将引用同一个数组:
int[] a = {2, 3, 5, 7, 11, 13};
int[] b = a;
System.out.println(b); // [I@4dc63996
System.out.println(b.length); // 6
System.out.println(Arrays.toString(b)); // [2, 3, 5, 7, 11, 13]
System.out.println(a); // [I@4dc63996
System.out.println(a.length); // 6
System.out.println(Arrays.toString(a)); // [2, 3, 5, 7, 11, 13]
在内存中它是这样的:
但,想让一个数组所有值拷贝到一个新的数组中,可以使用 Arrays 类的 copyOf() :
int[] a = {2, 3, 5, 7, 11, 13};
int[] b = Arrays.copyOf(a, a.length);
System.out.println(b); // [I@4dc63996
System.out.println(b.length); // 6
System.out.println(Arrays.toString(b)); // [2, 3, 5, 7, 11, 13]
System.out.println(a); // [I@4554617c * 注意这里,引用已经变了
System.out.println(a.length); // 6
System.out.println(Arrays.toString(a)); // [2, 3, 5, 7, 11, 13]
在内存中它是这样的:
copyOf() 还可以用来增加数组的长度:
int[] b = int[] b = Arrays.copyOf(a, 2 * a.length);
也就是说,改变 copyOf() 第二个值得长度,就可以进行数组的加长或者截取(可以使用 copyOfRage() 来进行更灵活的截取)。需要注意的是,加长后数组的值,就像上面说的那样,还未指定。
Java 中的 []
运算符被预定义为检查数组边界,而且没有指针运算,即不能通过 a 加 1 得到数组的下一个元素。
命令行参数
比如运行:
$ javac Main.java
$ java Main -g cruel world
那么在 public static void main(String[] args)
中的 args 数组会包含一下内容:
args[0]: "-g"
args[1]: "cruel"
args[2]: "world"
数组排序
数组排序可以用 Arrays 类中的 sort 方法:Arrays.sort(type[] a);
从 10 个数值中随机抽取 3 个,应该这样设计:
int sum = 10;
int n = 3;
int[] numbers = new int[sum];
int[] result = new int[n];
for (int i = 0; i < numbers.length; i++) {
numbers[i] = i + 1;
}
for (int i = 0; i < result.length; i++) {
int r = (int) (Math.random() * sum);
result[i] = numbers[r];
numbers[r] = numbers[sum - 1]; // 重点,与最后一位交换。使得上述代码成立
sum--;
}
不规则数组
Java 实际上没有多维数组,只有一维数组。多维数组被解释为“数组的数组”。
比如,int[][] a = new int[6][3];
在内存中是这样表示的:
可以看到 a 数组实际上是一个包含 6 个元素的数组,而每个元素又是由 3 个整形组成的数组。
这样就可以玩出很多不一样的东西,比如让两行交换:
int[] temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
也可以来构造不规则数组,即数组的每一行有不同的长度:
int max = 10;
int[][] odds = new int[max + 1][];
for(int n=0; n <= max; n++) {
odds[n] = new int[n+1]; // 每一行长度不一样了
}
API
int, array.length, 获取数组中的元素
java.util.Arrays 1.2
- static String toString(type[] a) 5.0
- static String deepToString(type[][] a)
返回包含 a 中数据元素的字符串,这些数据元素被放在括号内,并用逗号分隔。deepToString 可以打印多重数值。
- static type copyOf(type[] a, int length)
- static type copyOfRange(type[] a, int start, int end)
返回与 a 类型相同的一个数组,其长度为 length 或者 end-start ,数组元素为 a 的值。
- static void sort(type[] a)
采用优化的快速排序算法对数组进行排序。
- static int binarySearch(type[] a, type v)
- static int binarySearch(type[] a, int start, int end, type v)
保证 a 为顺序数组。采用二分搜索算法查找值 v 。如果查找成功,则返回相应的下标值;否则,返回一个负数值 r 。-r - 1 是为保持 a 有序 v 应插入的位置。
- static void fill(type[] a, type v)
将数组的所有数据元素值设置为 v 。
- static boolean equals(type[] a, type[] b)
如果两个数组大小相同,并且下标相同的元素都对应相等,返回 true。