数组
数组概要
-
数组是一种引用数据类型,在内存中存储示意图如下:
-
-
数组是一组数据的集合 。
-
数组作为一种引用类型 。
-
数组元素的类0型可以是基本类型,也可以是引用类型,但同一个数组只能是同一种类型 。
-
数组作为对象,数组中的元素作为对象的属性,除此之外数组还包括一个成员属性 length, length 表示数组的长度 。
-
数组的长度在数组对象创建后就确定了,就无法再修改了 。
-
数组元素是有下标的,下标从 0 开始,也就是第一个元素的下标为 0,依次类推最后一个堆内存 length:n 元素 0 元素 1 ........ ....... 元素 n-1元素的下标为 n-1,我们可以通过数组的下标来访问数组的元素。
一维数组的声明和初始化
-
一维数组的声明格式有以下两种:
-
数组元素的类型[] 变量名称 。
public class Test{ int[] arr; }
-
数组元素的类型 变量名称[]。
public class Test{ int arr[]; }
-
-
一维数组初始化有两种方式:
-
静态初始化。
public class Test{ // 以int类型为例 int[] arr = {1,2,3,4,5,6}; // 以String类型为例 String[] arr2 = {"zhangsan" , "lishi" , "wangwu"}; }
-
动态初始化
public class Test{ // 声明一个长度为10的int类型数组,中括号中的数字代表长度 int[] arr = new int[10]; }
-
一维数组中元素的访问
-
数组中每一个元素都是有下标(index)的,下标从0开始,以1递增,访问arr数组中下标index元素的语法格式:arr[index]。
-
案例:
public class Test{ public static void main(String[] args){ // 创建一个数组 int[] arr = {4,2,6,1,3,5}; System.out.println("数组的长度=" + arr.length); // 获取第一个元素 System.out.println("第一个元素=" + arr[0]); // 获取第三个元素 System.out.println("第三个元素=" + arr[2]); // 获取最后一个元素 System.out.println("最后一个元素=" + arr[arr.length-1]); } }
运行结果如下:
-
一维数组的遍历
-
一维数组的遍历代码如下:
public class Test{ public static void main(String[] args){ // 创建一个数组 int[] arr = {4,2,6,1,3,5}; for (int i=0;i< arr.length;i++){ System.out.println(arr[i]); } } }
运行结果如下:
-
-
通过数组的遍历之后,我们可以给动态数组赋值:
public class Test{ public static void main(String[] args){ // 创建一个动态数组 int[] arr = new int[10]; System.out.print("赋值之前遍历:"); for (int i=0;i<arr.length;i++){ System.out.print(arr[i] + " "); } // 赋值 for (int i=0;i< arr.length;i++){ arr[i] = i; } System.out.print("\n赋值之后遍历:"); for (int i=0;i<arr.length;i++){ System.out.print(arr[i] + " "); } } }
运行结果如下:
-
通过for-each遍历数组
-
语法格式:
for(元素类型 遍历名:数组){ ...... }
-
例如:
public class Test{ public static void main(String[] args){ int[] arr = {5,4,6,3,2,7,1,8,9}; for (int x:arr){ System.out.print(x + " "); } } }
运行结果如下:
-
数组的拷贝与扩容
-
在Java语言中,数组的长度一旦确认之后,不可变。如果原数组中满了,还想存储更多的元素,只能创建一个空间更大的新数组,将原数组中的元素拷贝到新数组中,使用这种方法可以到达数组的扩容。
-
代码如下:
public class Test{ public static void main(String[] args){ // 原数组 int[] arr = {1,2,3,4,5}; System.out.print("原数组:"); for (int x:arr){ System.out.print(x + " "); } // 新数组 int[] arr2 = new int[10]; // 拷贝 System.arraycopy(arr,0,arr2,0,arr.length); System.out.print("\n新数组:"); for (int y:arr2){ System.out.print(y + " "); } } }
运行结果如下:
-
-
arraycopy方法是System类中提供的方法,是一个静态方法,解释如下:
System.arraycopy(Object src , int srcPos , Object dest , int destPos , int length); src:表示原数组 srcPos:表示原数组从哪个下标开始拷贝 dest:表示新数组 destPos:表示从新数组哪个下标开始存放 length:表示拷贝多少个元素
二维数组
-
二维数组声明与初始化
public class Test{ // 静态二维数组 int[][] arr = {{1,2,3} , {4,5,6} , {7,8,9}}; // 动态二维数组,表示5行5列 int[][] arr2 = new int[5][5]; }
-
二维数组的遍历
public class Test{ public static void main(String[] args){ int[][] arr = {{1,2,3} , {4,5,6} , {7,8,9}}; for (int i=0;i< arr.length;i++){ for (int j=0;j<arr[i].length;j++){ System.out.print(arr[i][j] + " "); } System.out.println(); } } }
运行结果如下:
-
方法调用时数组参数如何传递
-
代码如下:
public class Test{ public static void main(String[] args) { int[] arr1 = {1,2,3}; int[][] arr2 = {{1,2,3} , {4,5,6} , {7,8,9}}; Array array = new Array(); // 第一种方式传递 array.test1(arr1); array.test2(arr2); // 第二种方式传递 array.test1(new int[]{1,2,3}); array.test2(new int[][]{{1} , {2} , {3}}); } } class Array { // 一维数组作为参数 public void test1(int[] arr){ } // 二维数组作为参数 public void test2(int[][] arr){ } }
可变长参数
-
代码如下:
public class Test{ public static void show(int... nums){ } }
-
其中int... nums是可变长参数,注意三个点“...”,三个点放在数据类型后面。以上代码表示show方法可以接收0~N个int类型的参数。
-
这里需要注意的是,可变长参数在参数列表中只能出现1次,并且出现在参数列表中最后一个位置上,例如:
public class Test{ public static void show(int a, double b , String s ,int... nums){ } }
冒泡排序
-
代码如下:
public class Test{ public static void main(String[] args) { int[] arr = {5,2,3,1,6,4,9,7,8}; // 冒泡排序 for (int i=0;i<arr.length-1;i++){ for (int j=0;j<arr.length-1-i;j++){ if (arr[j] > arr[j+1]){ int temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; } } } // 遍历 for (int x:arr){ System.out.print(x + " "); } } }
-
运行结果如下:
-
二分查找(折半查找)
-
代码如下:
public class Test{ public static void main(String[] args) { int[] arr = {5,2,3,1,6,4,9,7,8}; // 二分查找(折半查找),必须建立在排序的基础上 for (int i=0;i<arr.length-1;i++){ for (int j=0;j<arr.length-1-i;j++){ if (arr[j] > arr[j+1]){ int temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; } } } System.out.println("排序之后的数组:" + Arrays.toString(arr)); int index = sort(arr,9); System.out.println("查找值下标为:" + index); } /** * 创建二分查找方法 * @param arr 传入一个排序的数组 * @param val 传入查找值 * @return 查找成功返回下标,查找失败返回-1 */ public static int sort(int[] arr , int val){ // 最左下标 int left = 0; // 最右下标 int right = arr.length-1; // 如果最左下标大于最右下标结束循环 while (left <= right){ // 计算中间下标 int mid = (left + right) / 2; if (arr[mid] == val){ return mid; } if (arr[mid] < val){ left = mid + 1; } if (arr[mid] > val){ right = mid - 1; } } return -1; } }
运行结果如下:
-
数组工具类Arrays
-
在JDK的类库中,实际上已经提供了数组相关的工具类:java.util.Arrays,通过这个数组工具类可以便捷的操作数组,对于Arrays工具类应该要掌握常用的方法。
-
Arrays.toString()方法
public class Test{ public static void main(String[] args){ int[] arr = {1,2,3,4,5}; // 参数是数组,返回一个字符串(数组中的元素) String arrayString = Arrays.toString(arr); System.out.println(arrayString); } }
运行结果如下:
-
-
Arrays.sort()方法
public class Test{ public static void main(String[] args){ int[] arr = {4,2,3,5,1}; // 参数是数组,该方法用来对数组排序 Arrays.sort(arr); System.out.println(Arrays.toString(arr)); } }
运行结果如下:
-
-
Arrays.binarySearch()方法
public class Test{ public static void main(String[] args){ int[] arr = {1,2,3,4,5}; // 二分查找方法,存在元素返回下标,不存在返回负数 int index = Arrays.binarySearch(arr,3); System.out.println("元素下标为:" + index); } }
运行结果如下:
-
-
Arrays.copyOf()方法
public class Test{ public static void main(String[] args){ int[] arr = {1,2,3,4,5}; // 通过原数组拷贝生成新数组,第一个参数:原数组,第二个参数:数组长度,原数组下标0开始拷贝。 int[] arr1 = Arrays.copyOf(arr,4); System.out.println(Arrays.toString(arr1)); int[] arr2 = Arrays.copyOf(arr,10); System.out.println(Arrays.toString(arr2)); } }
运行结果如下:
-
-
Arrays.fill()方法
public class Test{ public static void main(String[] args){ int[] arr = {1,2,3,4,5}; // 数组填充的方法,参数:原数组,开始下标(包括),结束下标(不包括),填充值 Arrays.fill(arr,1,4,100); System.out.println(Arrays.toString(arr)); } }
运行结果如下: