Java数组
数组的定义
数组是相同类型数据的有序集合,数组中每个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们
数组的声明和创建
-
声明数组变量的语法
dataType[] arrayRefVar;//首选方法 dataType arrayRefVar[];//效果相同,但不是首选
Java语言使用new来创建数组,语法如下
dataType[] arrayRefVar = new dataType[arraySize];
-
数组元素通过索引访问,从0开始,获取数组长度array.length
package com.yushuo.array; public class ArrayDemo01 { public static void main(String[] args) { //变量类型 变量名 = 变量值 int sum = 0; int[] nums;//声明一个数组 nums = new int[10];//创建一个数组,数组大小为10 //为数组赋值,如果没赋值,则为默认值,int的默认值是0 for (int i = 0; i < 10; i++) { nums[i] = i; } for (int i = 0; i < nums.length; i++) { sum += nums[i]; } System.out.println("0到9的总和为" + sum); } }
-
数组的特点
- 数组的长度是固定的,一旦被创建就不可改变
- 元素类型必须相同,不允许出现混合类型
- 元素可以是任意数据类型,包括基本类型和引用类型
- 数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他类型,数组对象本身就是在堆中的
初始化与Java内存分析
Java内存分析
-
堆:
存放new的对象和数组,可以被所有的线程共享,不会存放别的对象引用
-
栈:
存放基本变量类型(会包含这个基本类型的具体数值),引用对象的变量(会存放这个引用在堆里面的具体地址)
-
方法区:
可以被所有的线程共享,包含了所有的class和static变量
-
int[] nums;//声明一个数组
此时,栈内压入一个nums,堆中仍是空的
-
nums = new int[10];//创建一个数组,数组大小为10
此时,在堆中开辟一个内存空间,空间被分为10个大小为int类型的小块
-
为数组赋值,如果没赋值,则为默认值,int的默认值是0
此时,根据索引,在相应小块中添加值
初始化
package com.yushuo.array;
public class ArrayDemo02 {
public static void main(String[] args) {
//静态初始化: 创建 + 赋值
int a[] = {1,2,3,4,5,6,7,8,9};
//动态初始化: 包含默认初始化
int b[] = new int[10];
b[0] = 5;
}
}
下标越界
数组边界:下标的合法区间:[0,length-1],越界就会报错
ArrayIndexOutOfBoundsException:数组下标越界异常
数组的使用
-
For-Each循环
package com.yushuo.array; public class ArrayDemo03 { public static void main(String[] args) { int[] arrays = {1,2,3,4,5,6}; //for循环 for (int i = 0; i < arrays.length; i++) { System.out.println(arrays[i]); } //增强for循环 for (int array : arrays) { System.out.println(array); } } }
-
数组做方法入参、数组做返回值
package com.yushuo.array; public class ArrayDemo04 { public static void main(String[] args) { int[] arrays = {1,2,3,4,5,6,7,8,9}; printArray(arrays); arrays = resvrseArray(arrays); printArray(arrays); } //打印数组 public static void printArray(int[] arrays){ for (int array : arrays) { System.out.println(array); } } //反转数组 public static int[] resvrseArray(int[] arrays){ int[] reverseArray = new int[arrays.length]; for (int i = 0; i < arrays.length; i++) { reverseArray[arrays.length - 1 - i] = arrays[i]; } return reverseArray; } }
多维数组
多维数组:数组的数组,数组中的元素是数组
package com.yushuo.array;
public class ArrayDemo05 {
public static void main(String[] args) {
/**
* 4行2列
* arrays[0] = {1,2}
* arrays[1] = {2,3}
* arrays[2] = {3,4}
* arrays[3] = {4,5}
*/
int[][] arrays = {{1,2},{2,3},{3,4},{4,5}};
System.out.println(arrays.length);//4
System.out.println(arrays[0].length);//2
//需要通过两个变量才能具体定位
for (int i = 0; i < arrays.length; i++) {
for (int j = 0; j < arrays[i].length; j++) {
System.out.println(arrays[i][j]);
}
}
}
}
Arrays类
- 数组的工具类java.util.Arrays
- 由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays,从而可以对数据对象进行一些基本的操作
- Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而不用使用对象来调用(是不用而不是不能)
- 常用功能:
- 给数组赋值:通过fill方法
- 对数组排序:通过sort方法,按升序
- 比较数组:通过equals方法比较数组中元素值是否相等
- 查找数组元素:通过binarySearch方法能对排序号的数组进行二分查找法操作
package com.yushuo.array;
import java.util.Arrays;
public class ArrayDemo06 {
public static void main(String[] args) {
int[] arrays = {5,6,4,7,2,3,9,1,8,};
System.out.println(Arrays.toString(arrays));//打印数组
Arrays.sort(arrays);//升序排列
System.out.println(Arrays.toString(arrays));
Arrays.fill(arrays,0);//把数组元素全部填充为0
System.out.println(Arrays.toString(arrays));
}
}
冒泡排序
冒泡排序是最为出名的排序。复杂度O(n²)
-
原理(若要对大小为n的数组进行升序排列):
- 从第0个开始,每一个元素与后一个元素进行比较,如果前一个元素>后一个元素,两者交换位置,总共需要比较n-1次,最大的元素将会排在数组末端
- 从第0个开始,每一个元素与后一个元素进行比较,如果前一个元素>后一个元素,两者交换位置,由于最后一个元素经第一轮排序已经是最大元素,只需要比较n-2次,次大的元素将会排在数组末端倒数第二位
- 依次类推,知道全部的n-1轮排序完成
package com.yushuo.array; import java.util.Arrays; public class ArrayDemo07 { public static void main(String[] args) { int[] arrays = {5,6,4,7,2,3,9,1,8,}; System.out.println(Arrays.toString(arrays)); arrays = sort(arrays); System.out.println(Arrays.toString(arrays)); } //冒泡排序,升序 //此处因为会把array的值改变,函数为void的结果也是一样的 public static int[] sort(int[] arrays){ int temp = 0;//临时变量,便于变量交换 boolean flag;//flag是标志位,用以减少判断次数 //先进行一个for循环,arrays.length-1次 for (int i = 0; i < arrays.length - 1; i++) { flag = false; /** * flag是标志位,用以减少判断次数 * 每一轮排序开始前,设置flag为false,如果该轮排序经历数据交换,则flag为true * 如果未经历arrays.length-1轮排序,数组已经排序完成,此时不会进行数据交换 * 无数据交换,此轮排序结束后,flag为false,可以此作为结束排序序号,避免多余的比较 */ //第i次循环内嵌套一个for循环以进行排序,总共需要比较arrays.length-1-i次 for (int j = 0; j < arrays.length - 1 - i; j++) { if (arrays[j] > arrays[j+1]){ temp = arrays[j]; arrays[j] = arrays[j+1]; arrays[j+1] = temp; flag = true; } } if (flag == false){ return arrays; } } return arrays; } }
稀疏数组
-
当一个数组中大部分元素为0,或者为同一值的数组是,可以使用系数数组来保存该数组
-
稀疏数组的处理方式:
- 记录数组一共有几行几列,有多少个不同值
- 把具有不同值的元素和行列及值记录在一个小规模数组中,从而缩小程序的规模
如下图,数组总共6行7列,共8个值:
第1个值在0行3列,为22,第2个值在0行6列,为15,类推。
package com.yushuo.array;
public class ArrayDemo08 {
public static void main(String[] args) {
/**
* 五子棋游戏
* 创建一个二维数组,由于棋盘为11x11的,数组也是11x11
* 0:没有棋子、1:黑棋、2:白棋
*/
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 2;
System.out.println("原始的数组为:");
print(array1);
//转换为稀疏数组保存
int[][] array2 = normalToSparse(array1);
System.out.println("稀疏数组为:");
print(array2);
//稀疏数组还原
int[][] array3 = sparseToNormal(array2);
System.out.println("转换后的数组为:");
print(array3);
}
//打印数组
public static void print(int[][] arrays){
//增强for循环
for (int[] array : arrays) {
for (int i : array) {
System.out.print(i + "\t");
}
System.out.println();
}
}
//普通数组转换为稀疏数组
public static int[][] normalToSparse(int[][] normalArrays){
//计算有效值的个数
int sum = 0;
for (int[] normalArray : normalArrays) {
for (int i : normalArray) {
if (i != 0){
sum++;
}
}
}
System.out.println("有效值的个数为:" + sum);
//创建一个稀疏数组
int[][] sparseArray = new int[sum+1][3];
sparseArray[0][0] = normalArrays.length;
sparseArray[0][1] = normalArrays[0].length;
sparseArray[0][2] = sum;
//遍历原始数组,将非零值存储在稀疏数组中
int i1 = 1;
for (int i = 0; i < normalArrays.length; i++) {
for (int j = 0; j < normalArrays[i].length; j++) {
if (normalArrays[i][j] != 0){
sparseArray[i1][0] = i;
sparseArray[i1][1] = j;
sparseArray[i1][2] = normalArrays[i][j];
i1++;
}
}
}
return sparseArray;
}
//稀疏数组转换为普通数组
public static int[][] sparseToNormal(int[][] sparseArrays){
int[][] normalArray = new int[sparseArrays[0][0]][sparseArrays[0][1]];
for (int i = 1; i < sparseArrays.length; i++) {
normalArray[sparseArrays[i][0]][sparseArrays[i][1]] = sparseArrays[i][2];
}
return normalArray;
}
}