数组可以理解为 固定大小的、用来存储 相同类型 数据元素的数据容器,是一种数据类型(引用类型)。
预先知道数组内容,创建数组时即指定数组元素的值。
/* 数据类型[] 数组变量名 = {元素1,元素2,...,元素n}; 数据类型[] 数组变量名 = new 数据类型[]{元素1,元素2,...,元素n}; */ int[] arr1 = {1,2,3,4}; int[] arr2 = new int[]{1,2,3,4};
预先不知道数组内容,创建数组时指定数组长度,数组元素初始化为默认值(参考数据类型)。
/* 数据类型[] 数组变量名 = new 数据类型[数组长度]; */ String[] arrStr = new String[3]; // String 默认值 null
可以通过下标索引访问数组中的元素,索引从 0 开始,最大值 = 数组长度 - 1,可通过 数组.length
属性获得数组长度。
如果访问时索引超过最大值,会报 java.lang.ArrayIndexOutOfBoundsException
(数组下标越界异常)。
如果数组变量的引用为 null
,会报 java.lang.NullPointerException
(空指针异常)。
int[] arr1 = {1,2,3}; int ele = arr1[0]; arr1[1] = 12; System.out.println(arr1.length);
int[] datas = {1, 2, 4, 545, 11, 32, 13131, 4444}; for(int i = 0; i < datas.length; i++) { System.out.println(datas[i]); }
JDK1.5 引进了一种新的循环类型,被称为 For-Each 循环或者加强型循环。
int[] datas = {1, 2, 4, 545, 11, 32, 13131, 4444}; for(int ele: datas) { System.out.println(ele); }
多维数组可以看成数组的数组,比如二维数组就是一个特殊的一维数组,每个元素都是一个一维数组。
二维数组本质上是行列集合,要确定某一个元素需要行索引和列索引来进行定位。
int[][] arr1 = {{1,2},{3,4,5},{6}}; // 静态初始化 int[][] arr2 = new int[3][4]; // 动态初始化 System.out.println(arr1[1][1]); // 4
/* 打印一个 10 行的杨辉三角 */ int[][] yangHui = new int[10][]; for(int i = 0;i < yangHui.length; i++){ yangHui[i] = new int[i+1]; for(int j = 0; j < yangHui[i].length; j++){ if(j == 0 || j == yangHui[i].length - 1) { yangHui[i][j] = 1; } else { yangHui[i][j] = yangHui[i-1][j-1] + yangHui[i-1][j]; } System.out.print(yangHui[i][j] + " "); } System.out.println(""); }
int[] arr1 = {1,2,3,4}; // arr1 实际指向数组空间的首地址
Arrays 位于 java.util
包中,包含操纵数组的各种静态方法。
对于多维数组,使用 Arrays.deepToString。
// 基本类型,此处例举 int public static String toString(int[] arr) public static String toString(Object[] arr)
import java.util.Arrays; public class ArrayDemo { public static void main(String[] args) { int[] arr1 = {3,1,5,4,2,8,9}; System.out.println(arr1); System.out.println(Arrays.toString(arr1)); Human[] arr2 = {new Human("齐贝林",33)}; System.out.println(arr2); // [Lcom.hello.base.Human;@1b6d3586 System.out.println(Arrays.toString(arr2)); } } class Human { public String name; public int age; public Human(String name,int age){ this.name = name; this.age = age; } @Override public String toString() { return "Human{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
sort 方法默认是从小到大排序,如果希望按照从大到小排序,可以通过 Comparable 接口或者 Comparator 外部比较器接口的比较方法实现。
// 基本类型,此处例举 int public static void sort(int[] a) // 对象类要实现 Comparable 接口 public static void sort(Object[] a) // 通过 Comparator 外部比较器接口比较 public static <T> void sort(T[] var0, Comparator<? super T> var1)
import java.util.Arrays; import java.util.Comparator; public class ArrayDemo { public static void main(String[] args) { int[] nums = {2,5,0,4,6,-10}; Arrays.sort(nums); System.out.println(Arrays.toString(nums)); Human[] arrHuman1 = {new Human("龟仙人",100), new Human("齐贝林",33), new Human("雄霸",66)}; System.out.println(Arrays.toString(arrHuman1)); // 按年龄从小到大 Arrays.sort(arrHuman1, new Comparator<Human>() { @Override public int compare(Human t1, Human t2) { // 返回 -1 表示 t1 小于 t2,0 表示 t1 等于 t2,1 表示 t1 大于 t2 return t1.age - t2.age; } }); System.out.println(Arrays.toString(arrHuman1)); // 按年龄从大到小 Arrays.sort(arrHuman1, new Comparator<Human>() { @Override public int compare(Human t1, Human t2) { return t2.age - t1.age; } }); System.out.println(Arrays.toString(arrHuman1)); } } class Human { public String name; public int age; public Human(String name,int age){ this.name = name; this.age = age; } @Override public String toString() { return "Human{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
数组必须有序。
如果元素存在,返回第一次找到的元素下标,如果不存在,返回 -(插入点下标 + 1)
。
/* 基本类型,此处例举 int var0 数组 var1 目标元素 */ public static int binarySearch(int[] var0, int var1) { return binarySearch0((int[])var0, 0, var0.length, (int)var1); } private static int binarySearch0(int[] var0, int var1, int var2, int var3) { int var4 = var1; // 起始位置 int var5 = var2 - 1; // 结束位置 while(var4 <= var5) { int var6 = var4 + var5 >>> 1; // 中间位置 int var7 = var0[var6]; if (var7 < var3) { // 大于中间位置的值 var4 = var6 + 1; } else { if (var7 <= var3) { // 等于中间位置的值 return var6; } // 大于中间位置的值 var5 = var6 - 1; } } return -(var4 + 1); }
int[] arr = {0,2,3,4,10}; System.out.println(Arrays.binarySearch(arr,2)); // 1 System.out.println(Arrays.binarySearch(arr,5)); // -5
基于原数组,复制一个新数组,实际是调用 System.arraycopy 方法进行拷贝。
/* src - 源数组。 srcPos - 源数组中的起始位置。 dest - 目标数组。 destPos - 目标数组中的起始位置。 length - 要复制的数组元素的数量。 */ public static void arraycopy(Object src,int srcPos,Object dest, int destPos,int length)
/* 基本类型,此处例举 int var0 - 源数组 var1 - 拷贝长度 */ public static int[] copyOf(int[] var0, int var1) { int[] var2 = new int[var1]; System.arraycopy(var0, 0, var2, 0, Math.min(var0.length, var1)); return var2; } /* var0 - 源数组 var1 - 拷贝起始位置 var2 - 拷贝终点位置(不抱含) */ public static int[] copyOfRange(int[] var0, int var1, int var2) { int var3 = var2 - var1; if (var3 < 0) { throw new IllegalArgumentException(var1 + " > " + var2); } else { int[] var4 = new int[var3]; System.arraycopy(var0, var1, var4, 0, Math.min(var0.length - var1, var3)); return var4; } }
int[] arrA = {3,11,5,7,2,1,9,6,12,1}; int[] arrB = Arrays.copyOf(arrA,arrA.length); int[] arrC = Arrays.copyOfRange(arrB,1,3); System.out.println(Arrays.toString(arrB)); System.out.println(Arrays.toString(arrC));
对于多维数组,使用 Arrays.deepHashCode。
public static int hashCode(int[] var0) { if (var0 == null) { return 0; } else { int var1 = 1; int[] var2 = var0; int var3 = var0.length; for(int var4 = 0; var4 < var3; ++var4) { int var5 = var2[var4]; var1 = 31 * var1 + var5; } return var1; } }
数组长度和数组元素都相等时才相等。
对于多维数组,使用 Arrays.deepEquals。
public static boolean equals(int[] var0, int[] var1) { if (var0 == var1) { return true; } else if (var0 != null && var1 != null) { int var2 = var0.length; if (var1.length != var2) { return false; } else { for(int var3 = 0; var3 < var2; ++var3) { if (var0[var3] != var1[var3]) { return false; } } return true; } } else { return false; } }
import java.util.AbstractList; import java.util.Arrays; import java.util.List; import java.util.Objects; public class ArrayDemo { public static void main(String[] args) { int[] arr1 = {1,2,3}; String[] arr2 = {"1","2","3"}; // List<Object> list1 = Arrays.asList(arr1); List<Object> list1 = Demo.asList(arr1); List<Object> list2 = Demo.asList(arr2); for (Object obj1:list1) { System.out.println(obj1.toString()); } for (Object obj2: list2) { System.out.println(obj2.toString()); } } } /** 仿写 Arrays 的 asList 方法 */ class Demo{ /* T...args,可以理解为数组,T 泛型,因此只能是引用类型数组 基本类型会将整个数组作为 args 的元素 */ public static <T> List<T> asList(T...args){ return new Demo.DemoList(args); } public static class DemoList<E> extends AbstractList<E> { private final E[] a; DemoList(E[] var1) { this.a = Objects.requireNonNull(var1); } @Override public E get(int var1) { return this.a[var1]; } @Override public int size() { return this.a.length; } } }