爆肝一个月,Java 从入门到精通05 - 数组操作
遍历数组我们在Java程序基础里介绍了数组这种数据类型。有了数组我们还需要来操作它。而数组最常见的一个操作就是遍历。通过for循环就可以遍历数组。因为数组的每个元素都可以通过索引来访问因此使用标准的for循环可以完成一个数组的遍历// 遍历数组 public class Main { public static void main(String[] args) { int[] ns { 1, 4, 9, 16, 25 }; for (int i0; ins.length; i) { int n ns[i]; System.out.println(n); } } }为了实现for循环遍历初始条件为i0因为索引总是从0开始继续循环的条件为ins.length因为当ins.length时i已经超出了索引范围索引范围是0~ns.length-1每次循环后i。第二种方式是使用for each循环直接迭代数组的每个元素// 遍历数组 public class Main { public static void main(String[] args) { int[] ns { 1, 4, 9, 16, 25 }; for (int n : ns) { System.out.println(n); } } }注意在for (int n : ns)循环中变量n直接拿到ns数组的元素而不是索引。显然for each循环更加简洁。但是for each循环无法拿到数组的索引因此到底用哪一种for循环取决于我们的需要。打印数组内容直接打印数组变量得到的是数组在JVM中的引用地址int[] ns { 1, 1, 2, 3, 5, 8 }; System.out.println(ns); // 类似 [I7852e922这并没有什么意义因为我们希望打印的数组的元素内容。因此使用for each循环来打印它int[] ns { 1, 1, 2, 3, 5, 8 }; for (int n : ns) { System.out.print(n , ); }使用for each循环打印也很麻烦。幸好Java标准库提供了Arrays.toString()可以快速打印数组内容// 遍历数组 import java.util.Arrays; public class Main { public static void main(String[] args) { int[] ns { 1, 1, 2, 3, 5, 8 }; System.out.println(Arrays.toString(ns)); } }数组排序对数组进行排序是程序中非常基本的需求。常用的排序算法有冒泡排序、插入排序和快速排序等。我们来看一下如何使用冒泡排序算法对一个整型数组从小到大进行排序// 冒泡排序 import java.util.Arrays; public class Main { public static void main(String[] args) { int[] ns { 28, 12, 89, 73, 65, 18, 96, 50, 8, 36 }; // 排序前: System.out.println(Arrays.toString(ns)); for (int i 0; i ns.length - 1; i) { for (int j 0; j ns.length - i - 1; j) { if (ns[j] ns[j1]) { // 交换ns[j]和ns[j1]: int tmp ns[j]; ns[j] ns[j1]; ns[j1] tmp; } } } // 排序后: System.out.println(Arrays.toString(ns)); } }冒泡排序的特点是每一轮循环后最大的一个数被交换到末尾因此下一轮循环就可以“刨除”最后的数每一轮循环都比上一轮循环的结束位置靠前一位。另外注意到交换两个变量的值必须借助一个临时变量。像这么写是错误的int x 1; int y 2; x y; // x现在是2 y x; // y现在还是2正确的写法是int x 1; int y 2; int t x; // 把x的值保存在临时变量t中, t现在是1 x y; // x现在是2 y t; // y现在是t的值1实际上Java的标准库已经内置了排序功能我们只需要调用JDK提供的Arrays.sort()就可以排序// 排序 import java.util.Arrays; public class Main { public static void main(String[] args) { int[] ns { 28, 12, 89, 73, 65, 18, 96, 50, 8, 36 }; Arrays.sort(ns); System.out.println(Arrays.toString(ns)); } }必须注意对数组排序实际上修改了数组本身。例如排序前的数组是int[] ns { 9, 3, 6, 5 };在内存中这个整型数组表示如下┌───┬───┬───┬───┐ ns───▶│ 9 │ 3 │ 6 │ 5 │ └───┴───┴───┴───┘当我们调用Arrays.sort(ns);后这个整型数组在内存中变为┌───┬───┬───┬───┐ ns───▶│ 3 │ 5 │ 6 │ 9 │ └───┴───┴───┴───┘即变量ns指向的数组内容已经被改变了。如果对一个字符串数组进行排序例如String[] ns { banana, apple, pear };排序前这个数组在内存中表示如下┌──────────────────────────────────┐ ┌───┼──────────────────────┐ │ │ │ ▼ ▼ ┌───┬─┴─┬─┴─┬───┬────────┬───┬───────┬───┬──────┬───┐ ns ─────▶│░░░│░░░│░░░│ │banana│ │apple│ │pear│ │ └─┬─┴───┴───┴───┴────────┴───┴───────┴───┴──────┴───┘ │ ▲ └─────────────────┘调用Arrays.sort(ns);排序后这个数组在内存中表示如下┌──────────────────────────────────┐ ┌───┼──────────┐ │ │ │ ▼ ▼ ┌───┬─┴─┬─┴─┬───┬────────┬───┬───────┬───┬──────┬───┐ ns ─────▶│░░░│░░░│░░░│ │banana│ │apple│ │pear│ │ └─┬─┴───┴───┴───┴────────┴───┴───────┴───┴──────┴───┘ │ ▲ └──────────────────────────────┘原来的3个字符串在内存中均没有任何变化但是ns数组的每个元素指向变化了。多维数组二维数组二维数组就是数组的数组。定义一个二维数组如下// 二维数组 public class Main { public static void main(String[] args) { int[][] ns { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; System.out.println(ns.length); // 3 } }因为ns包含3个数组因此ns.length为3。实际上ns在内存中的结构如下┌───┬───┬───┬───┐ ┌───┐ ┌──▶│ 1 │ 2 │ 3 │ 4 │ ns ─────▶│░░░│──┘ └───┴───┴───┴───┘ ├───┤ ┌───┬───┬───┬───┐ │░░░│─────▶│ 5 │ 6 │ 7 │ 8 │ ├───┤ └───┴───┴───┴───┘ │░░░│──┐ ┌───┬───┬───┬───┐ └───┘ └──▶│ 9 │10 │11 │12 │ └───┴───┴───┴───┘如果我们定义一个普通数组arr0然后把ns[0]赋值给它// 二维数组 public class Main { public static void main(String[] args) { int[][] ns { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; int[] arr0 ns[0]; System.out.println(arr0.length); // 4 } }实际上arr0就获取了ns数组的第0个元素。因为ns数组的每个元素也是一个数组因此arr0指向的数组就是{ 1, 2, 3, 4 }。在内存中结构如下arr0 ─────┐ ▼ ┌───┬───┬───┬───┐ ┌───┐ ┌──▶│ 1 │ 2 │ 3 │ 4 │ ns ─────▶│░░░│──┘ └───┴───┴───┴───┘ ├───┤ ┌───┬───┬───┬───┐ │░░░│─────▶│ 5 │ 6 │ 7 │ 8 │ ├───┤ └───┴───┴───┴───┘ │░░░│──┐ ┌───┬───┬───┬───┐ └───┘ └──▶│ 9 │10 │11 │12 │ └───┴───┴───┴───┘访问二维数组的某个元素需要使用array[row][col]例如System.out.println(ns[1][2]); // 7二维数组的每个数组元素的长度并不要求相同例如可以这么定义ns数组int[][] ns { { 1, 2, 3, 4 }, { 5, 6 }, { 7, 8, 9 } };这个二维数组在内存中的结构如下┌───┬───┬───┬───┐ ┌───┐ ┌──▶│ 1 │ 2 │ 3 │ 4 │ ns ─────▶│░░░│──┘ └───┴───┴───┴───┘ ├───┤ ┌───┬───┐ │░░░│─────▶│ 5 │ 6 │ ├───┤ └───┴───┘ │░░░│──┐ ┌───┬───┬───┐ └───┘ └──▶│ 7 │ 8 │ 9 │ └───┴───┴───┘要打印一个二维数组可以使用两层嵌套的for循环for (int[] arr : ns) { for (int n : arr) { System.out.print(n); System.out.print(, ); } System.out.println(); }或者使用Java标准库的Arrays.deepToString()// 二维数组 import java.util.Arrays; public class Main { public static void main(String[] args) { int[][] ns { { 1, 2, 3, 4 }, { 5, 6 }, { 7, 8, 9 } }; System.out.println(Arrays.deepToString(ns)); } }三维数组三维数组就是二维数组的数组。可以这么定义一个三维数组int[][][] ns { { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }, { {10, 11}, {12, 13} }, { {14, 15, 16}, {17, 18} } };它在内存中的结构如下┌───┬───┬───┐ ┌───┐ ┌──▶│ 1 │ 2 │ 3 │ ┌──▶│░░░│──┘ └───┴───┴───┘ │ ├───┤ ┌───┬───┬───┐ │ │░░░│─────▶│ 4 │ 5 │ 6 │ │ ├───┤ └───┴───┴───┘ │ │░░░│──┐ ┌───┬───┬───┐ ┌───┐ │ └───┘ └──▶│ 7 │ 8 │ 9 │ ns ────▶│░░░│──┘ └───┴───┴───┘ ├───┤ ┌───┐ ┌───┬───┐ │░░░│─────▶│░░░│─────▶│10 │11 │ ├───┤ ├───┤ └───┴───┘ │░░░│──┐ │░░░│──┐ ┌───┬───┐ └───┘ │ └───┘ └──▶│12 │13 │ │ └───┴───┘ │ ┌───┐ ┌───┬───┬───┐ └──▶│░░░│─────▶│14 │15 │16 │ ├───┤ └───┴───┴───┘ │░░░│──┐ ┌───┬───┐ └───┘ └──▶│17 │18 │ └───┴───┘如果我们要访问三维数组的某个元素例如ns[2][0][1]只需要顺着定位找到对应的最终元素15即可。理论上我们可以定义任意的N维数组。但在实际应用中除了二维数组在某些时候还能用得上更高维度的数组很少使用。命令行参数Java程序的入口是main方法而main方法可以接受一个命令行参数它是一个String[]数组。这个命令行参数由JVM接收用户输入并传给main方法public class Main { public static void main(String[] args) { for (String arg : args) { System.out.println(arg); } } }我们可以利用接收到的命令行参数根据不同的参数执行不同的代码。例如实现一个-version参数打印程序版本号public class Main { public static void main(String[] args) { for (String arg : args) { if (-version.equals(arg)) { System.out.println(v 1.0); break; } } } }上面这个程序必须在命令行执行我们先编译它$ javac Main.java然后执行的时候给它传递一个-version参数$ java Main -version v 1.0这样程序就可以根据传入的命令行参数作出不同的响应。喜欢这个系列的同学可以关注我爆肝一个月Python 从入门到精通