数组是一种数据结构,用来存储同一类型值的集合。通过一个整型下标可以访问数组中的每一个值。
声明数组:

  1. int[] a; // 声明
  2. int a[]; // 声明
  3. int[] a = new int[100]; // 声明并初始化可以存储 100 个整数的数组
  4. int[] a = {2, 3, 5, 7, 11}; // 创建数组并赋予初始值
  5. int[] a = new int[] {17, 19, 23, 29, 31, 37}; // 与上面一样
  6. int[] a = new int[0]; // 创建一个长度为 0 的数组。注意,与 null 的区别
  7. double[][] a = new double[10][10]; // 二维数组
  8. int[][] a = { // 二维数组初始化
  9. {16, 3, 2, 13},
  10. {5, 10, 11, 8},
  11. {9, 6, 7, 12},
  12. {4, 15, 14, 1},
  13. };
  14. int[][] a = new int[10][]; // 创建一个具有行数的数组

创建一个数组时,如果没有指定值。数字数组都初始化为 0 ;boolean 数组都初始化为 false;对象数组都初始化为 null。表示这些数组的元素还未存放任何值。
一旦创建了数组,就不能再改变它的大小(尽管可以改变每一个数组元素)。
Java 中有一个增强型 for 循环,可以不必关注下标值(当然,如果要用到下标值还是得用传统的 for 循环):

  1. for(int element : a)

其中 a 必须是一个数组或者是一个实现了 Iterable 接口的类对象(例如 ArrayList )。

数组拷贝

在 Java 中,可以直接将一个数组变量拷贝给另一个变量。这时,两个变量将引用同一个数组:

  1. int[] a = {2, 3, 5, 7, 11, 13};
  2. int[] b = a;
  3. System.out.println(b); // [I@4dc63996
  4. System.out.println(b.length); // 6
  5. System.out.println(Arrays.toString(b)); // [2, 3, 5, 7, 11, 13]
  6. System.out.println(a); // [I@4dc63996
  7. System.out.println(a.length); // 6
  8. System.out.println(Arrays.toString(a)); // [2, 3, 5, 7, 11, 13]

在内存中它是这样的:
copy_arrays_==
但,想让一个数组所有值拷贝到一个新的数组中,可以使用 Arrays 类的 copyOf() :

  1. int[] a = {2, 3, 5, 7, 11, 13};
  2. int[] b = Arrays.copyOf(a, a.length);
  3. System.out.println(b); // [I@4dc63996
  4. System.out.println(b.length); // 6
  5. System.out.println(Arrays.toString(b)); // [2, 3, 5, 7, 11, 13]
  6. System.out.println(a); // [I@4554617c * 注意这里,引用已经变了
  7. System.out.println(a.length); // 6
  8. System.out.println(Arrays.toString(a)); // [2, 3, 5, 7, 11, 13]

在内存中它是这样的:
copy_arrays_copyOf
copyOf() 还可以用来增加数组的长度:

  1. int[] b = int[] b = Arrays.copyOf(a, 2 * a.length);

也就是说,改变 copyOf() 第二个值得长度,就可以进行数组的加长或者截取(可以使用 copyOfRage() 来进行更灵活的截取)。需要注意的是,加长后数组的值,就像上面说的那样,还未指定。
Java 中的 [] 运算符被预定义为检查数组边界,而且没有指针运算,即不能通过 a 加 1 得到数组的下一个元素。

命令行参数

比如运行:

  1. $ javac Main.java
  2. $ java Main -g cruel world

那么在 public static void main(String[] args) 中的 args 数组会包含一下内容:

  1. args[0]: "-g"
  2. args[1]: "cruel"
  3. args[2]: "world"

数组排序

数组排序可以用 Arrays 类中的 sort 方法:Arrays.sort(type[] a);
从 10 个数值中随机抽取 3 个,应该这样设计:

  1. int sum = 10;
  2. int n = 3;
  3. int[] numbers = new int[sum];
  4. int[] result = new int[n];
  5. for (int i = 0; i < numbers.length; i++) {
  6. numbers[i] = i + 1;
  7. }
  8. for (int i = 0; i < result.length; i++) {
  9. int r = (int) (Math.random() * sum);
  10. result[i] = numbers[r];
  11. numbers[r] = numbers[sum - 1]; // 重点,与最后一位交换。使得上述代码成立
  12. sum--;
  13. }

不规则数组

Java 实际上没有多维数组,只有一维数组。多维数组被解释为“数组的数组”。
比如,int[][] a = new int[6][3]; 在内存中是这样表示的:
array_of_arrays
可以看到 a 数组实际上是一个包含 6 个元素的数组,而每个元素又是由 3 个整形组成的数组。
这样就可以玩出很多不一样的东西,比如让两行交换:

  1. int[] temp = a[i];
  2. a[i] = a[i+1];
  3. a[i+1] = temp;

也可以来构造不规则数组,即数组的每一行有不同的长度:

  1. int max = 10;
  2. int[][] odds = new int[max + 1][];
  3. for(int n=0; n <= max; n++) {
  4. odds[n] = new int[n+1]; // 每一行长度不一样了
  5. }

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。