数组基础
数组
数组的定义
-
数组是相同类型数据的有序集合。
-
数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而来。
-
其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。
数组声明创建
-
首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语句:
1 int[] array; // 首选的方法 2 String array1[]; // 效果相同,但不是首选
-
Java语言使用new操作符来创建数组,语法如下:
1 int[] array = new int[3]; // 创建一个int类型,长度为3的整数数组
-
数组的元素是通过索引访问的,数组索引从0开始。
-
获取数组长度:
1 arrays.lenth
-
代码示例:
1 package com.basic; 2 3 //创建一个数组,赋值并遍历 4 5 public class Demo14 { 6 public static void main(String[] args) { 7 int[] array = new int[10]; // 定义int类型数组,长度为10 8 9 // 给array中的元素赋值 10 // 没有赋值的元素将会赋一个对应类型的默认值 11 for (int i = 0; i < array.length; i++) { 12 array[i] = i + 1; 13 } 14 15 // for循环遍历数组 16 for (int i = 0; i < array.length; i++) { 17 System.out.println("array[" + i + "] = " + array[i]); 18 } 19 20 // foreach循环遍历数组 21 for (int i:array) { 22 System.out.println(i); 23 } 24 25 // 打印array中的某个元素 26 System.out.println(array[5]); 27 } 28 29 }
java内存分析
-
堆:存放new的对象和数组
可以被所有的线程共享,不会存放别的对象引用
-
栈:存放基本变量类型(会存放这个引用在堆里面的具体地址)
引用对象的变量(会存放这个引用在堆里面的具体地址)
-
方法区:可以被所有的线程共享
包含了所有的class和static变量
三种初始化
-
静态初始化
1 int[] a = {1,2,3}; 2 Man[] mans = {new Man(1,1),new Man(2,2)};
-
动态初始化
1 int[] a = new int[2]; 2 a[0] = 1; 3 a[1] = 2;
-
数组的默认初始化
数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
数组的特点
-
其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
-
其元素必须是相同类型,不允许出现混合类型。
-
数组中的元素可以是任何数据类型,包括基本类型和引用类型。
-
数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。
数组本身就是对象,Java中对象是在堆中的,以此数组无论保存原始类型还是其他对象类型,
数组对象本身是在堆中的。
数组边界
-
下标的合法区间:[0 , length - 1],如果越界就会报错;
1 public static void main(String[] args) { 2 int[] a = new int[2]; 3 System.out.println(a[2]); 4 }
-
ArrayIndexOutOfBoundsException:数组下标越界异常!
-
小结:
-
数组是相同数据类型(数据类型可以为任意类型)的有序集合
-
数组也是对象。数组元素相当于对象的成员变量
-
数组长度是确定的,不可变的。如果越界,则报:ArrayIndexOutOfBoundsException
-
数组使用
-
for循环
-
For-Each循环
-
数组作方法入参
-
数组做返回值
1 package com.array; 2 3 // 数组的使用 4 5 import java.util.Arrays; 6 7 public class Demo01 { 8 public static void main(String[] args) { 9 // 创建一个int类型的数组 10 int[] arrays = new int[10]; 11 12 // 通过for循环给数组arrays赋值 13 for (int i = 0; i < arrays.length; i++) { 14 arrays[i] = i + 1; 15 } 16 17 // 通过for循环打印数组arrays 18 for (int i = 0; i < arrays.length; i++) { 19 System.out.println("arrays[" + i + "] = " + arrays[i]); 20 } 21 22 // foreach循环通常用来遍历数组 23 for (int array : arrays) { 24 System.out.print(array + " "); 25 } 26 System.out.println(); 27 28 // 调用打印方法 29 printArray(arrays); 30 31 // 调用反转方法 32 int[] reserveArray = reserve(arrays); 33 printArray(reserveArray); 34 } 35 36 // 数组作方法入参,打印数组 37 public static void printArray(int[] arrays){ 38 System.out.println(Arrays.toString(arrays)); 39 } 40 41 // 数组作为返回值,反转方法 42 public static int[] reserve(int[] arrays){ 43 int[] reserveArray = new int[arrays.length]; 44 for (int i = 0; i < arrays.length; i++) { 45 reserveArray[i] = arrays[arrays.length - 1 - i]; 46 } 47 return reserveArray; 48 } 49 }
多维数组
-
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
-
二维数组
1 int[][] a = new int[2][5];
-
解析:以上二维数组a可以看成一个两行五列的数组。
-
二维数组的使用:
1 package com.array; 2 3 // 二维数组的使用 4 5 import java.util.Arrays; 6 7 public class Demo02 { 8 public static void main(String[] args) { 9 // 创建一个int类型的二维数组 10 int[][] arrays = new int[2][3]; 11 12 // 使用for循环给二维数组arrays赋值 13 for (int i = 0; i < arrays.length; i++) { 14 for (int j = 0; j < arrays[i].length; j++) { 15 arrays[i][j] = i * (arrays.length + 1) + j + 1; 16 } 17 } 18 19 // 输出数组中的某个元素 20 System.out.println(Arrays.toString(arrays[0])); 21 System.out.println("arrays[1][1] = " + arrays[1][1]); 22 23 // 使用for循环遍历数组 24 for (int i = 0; i < arrays.length; i++) { 25 for (int j = 0; j < arrays[i].length; j++) { 26 System.out.print(arrays[i][j] + " "); 27 } 28 System.out.println(); 29 } 30 System.out.println("============="); 31 32 // 使用foreach遍历数组 33 for (int[] array : arrays) { 34 for (int i : array) { 35 System.out.print(i + " "); 36 } 37 System.out.println(); 38 } 39 } 40 }
Arrays类
-
数组的工具类java.util.Arrays
-
由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。
-
查看JDK帮助文档
-
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用(注意:“是”不用“而不是”不能“)
-
具有以下常用功能
-
给数组赋值:通过fill方法。
-
对数组排序:通过sort方法,按升序。
-
比较数组:通过equals方法比较数组中元素是否相等。
-
查找数组元素:通过binarySearch() 方法对排序好的数组进行二分查找法操作。
-
1 package com.array; 2 3 // Arrays类的使用 4 5 import java.util.Arrays; 6 7 public class Demo03 { 8 public static void main(String[] args) { 9 int[] arrays = new int[10]; 10 // 使用fill()方法 11 Arrays.fill(arrays,1); 12 // 使用toString()方法打印数组内容 13 System.out.println(Arrays.toString(arrays)); 14 15 Arrays.fill(arrays,4,8,2); // 将索引4到8的数组元素赋值为2 16 System.out.println(Arrays.toString(arrays)); 17 18 boolean[] b = new boolean[10]; 19 Arrays.fill(b,true); 20 Arrays.fill(b,6,9,false); 21 System.out.println(Arrays.toString(b)); 22 23 int[] arrays1 = {1,2,3}; 24 int[] arrays2 = {1,2,3}; 25 int[] arrays3 = {1,2,5}; 26 // equals方法比较数组中元素值是否相等 27 System.out.println(Arrays.equals(arrays1,arrays2)); // true 28 System.out.println(Arrays.equals(arrays1,arrays3)); // false 29 30 // 使用binarySearch方法能对排序好的数组进行二分查找法操作 31 int[] arrays4 = {3,6,2,1,8,9,4}; 32 Arrays.sort(arrays4); 33 System.out.println(Arrays.toString(arrays4)); 34 System.out.println(Arrays.binarySearch(arrays4,6)); // 4 35 System.out.println(Arrays.binarySearch(arrays4,5)); // -5 36 // 如果找不到指定元素,则返回一个负值,返回 -(插入点)-1 37 // 插入点为数组中第一个比查找元素大的数组元素的索引值 38 } 39 }
冒泡排序
-
冒泡排序无疑是最为出名的排序算法之一,总共有八大排序!
-
冒泡排序的代码包括两层循环,外层冒泡轮数,里层依次比较,江湖中人人皆知。
-
我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为O(n2)。
-
思考:如何优化?
1 package com.array; 2 3 /* 冒泡排序 4 * 1. 比较数组中两个相邻的元素,如果第一个数比第二个数大,则交换它们的位置 5 * 2. 每一次比较,都会产生一个最大、或者最小的数字 6 * 3. 下一轮则可以少一次排序 7 * 4. 依次循环,直到结束 8 * */ 9 10 import java.util.Arrays; 11 12 public class Demo04 { 13 public static void main(String[] args) { 14 int[] arrays = {3,6,8,5,4,1,2,9}; 15 System.out.println(Arrays.toString(arrays)); 16 sort(arrays); 17 System.out.println(Arrays.toString(arrays)); 18 } 19 20 public static void sort(int[] arrays) { 21 for (int i = 0; i < arrays.length - 1; i++) { 22 for (int j = 0; j < arrays.length - 1 - i; j++) { 23 if (arrays[j + 1] < arrays[j]){ 24 int temp = arrays[j + 1]; 25 arrays[j + 1] = arrays[j]; 26 arrays[j] = temp; 27 } 28 } 29 } 30 } 31 }
稀疏数组
-
当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
-
稀疏数组的处理方式是:
-
记录数组一共有几行几列,有多少个有效值
-
把具有有效值的元素的行、列及值记录在一个小规模的数组中,从而缩小程序的规模
-
-
如图,左边是原始数组,右边是稀疏数组
1 package com.array; 2 3 // 稀疏数组 4 5 public class Demo05 { 6 public static void main(String[] args) { 7 int[][] array1 = new int[6][6]; 8 array1[1][2] = 5; 9 array1[2][4] = 6; 10 array1[3][3] = 8; 11 array1[4][0] = 9; 12 array1[5][4] = 7; 13 int sum = 0; // 记录有效值 14 for (int i = 0; i < array1.length; i++) { 15 for (int j = 0; j < array1[i].length; j++) { 16 if (array1[i][j] != 0) { 17 sum++; 18 } 19 } 20 } 21 22 // 打印array1数组 23 for (int[] ints : array1) { 24 for (int anInt : ints) { 25 System.out.print(anInt + " "); 26 } 27 System.out.println(); 28 } 29 System.out.println("array1有效值的个数:" + sum); // sum = 5 30 31 // 创建稀疏数组 32 int[][] array2 = new int[sum + 1][3]; 33 array2[0][0] = 6; 34 array2[0][1] = 6; 35 array2[0][2] = sum; // 表示array1有6行6列,sum个有效值 36 37 // 遍历array1数组,给array2赋值 38 int count = 0; // 用来计数 39 for (int i = 0; i < array1.length; i++) { 40 for (int j = 0; j < array1[i].length; j++) { 41 if (array1[i][j] != 0) { 42 count ++; 43 array2[count][0] = i; 44 array2[count][1] = j; 45 array2[count][2] = array1[i][j]; 46 } 47 } 48 } 49 50 // 打印array2数组 51 for (int[] ints : array2) { 52 for (int anInt : ints) { 53 System.out.print(anInt + " "); 54 } 55 System.out.println(); 56 } 57 } 58 }