数组
数组
什么是数组
数组是相同类型数据的有序集合
数组描述的是相同类型的若干个数据,按照一定的先后顺序排列组合在一起
每一个数据称作为一个数组元素,通过下标可以访问它们
为什么需要数组
假如需要创建100个int类型的对象,那我们不是需要100个int类型对象,操作繁琐且不简洁,而数组可以存储它们
声明数组
数据类型[] 数组名; //首选
数据类型 数组名[]; //其次 这个是由于是来自c语言,建议不要使用这个
创建数组
数据类型[] 数组名=new 数据类型[数组长度]
数组通过索引(下标)来访问它的,索引从0开始
获取长度:数组名.length
public static void main(String[] args) {
int[] nums=new int[4]; //创建一个数组
nums[0]=1; //通过下标来存储值,因为数组下标从0开始,总共长度4,说明数组下标为4-1=3
nums[1]=2;
nums[2]=3;
nums[3]=4;
//循环遍历数组的值
for (int i = 0; i < nums.length ; i++) { //nums.length获取数组的长度
System.out.println(nums[i]); //访问数组的值,也是通过下标来访问
//i的值为0,数组长度为4,i要小于4,所以只有0,1,2,3
//假如有一个没有赋值 int的默认是为0
//不懂默认值 https://www.cnblogs.com/ShuaiStudy/p/13969156.html
}
}
内存分析
堆:存放new的对象和数组,可以被所有的线程共享,不会存放别的对象引用
栈:存放基本类型(包含这个基本类型的具体数值),引用对象的变量(会存放这个引用在堆里面的具体地址)
方法区:可以被所有的线程共享,包含所有的class和static变量(暂时了解一下即可)

数组的初始化
- 静态初始化
int[] array={1,2,3,4}
- 动态初始化
int[] array=new int[2]
array[0]=1;
array[1]=2;
- 数组默认初始化
数组的初始化默认值:https://www.cnblogs.com/ShuaiStudy/p/13969156.html
数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量的方式别隐式初始化
数组的四个基本特点
- 其长度是确定的,数组一旦被创建,它的大小不可以被改变
- 其元素必须是相同类型,不能又混合类型
- 数组元素可以任何数据类型
- 数组变量属引用类型,数组可以看成一个对象,数组的每个元素相当于该对象的成员变量
- 数组本身就是对象,对象是在堆中,数组的对象本身是在堆中的
下标越界
int[] array=new int[2];
array[2]=2; //由于数组的下标从0开始,所有下标只有0和1,当给它这个数组的下标超过本身下标,就会报错
ArrayIndexOutOfBoundsException:当看到这个错误就是数组下标越界了
数组的使用
for循环和foreach循环
public static void main(String[] args) {
int[] nums=new int[4];
nums[0]=1;
nums[1]=2;
nums[2]=3;
nums[3]=4;
//输出数组的值
for (int i = 0; i < nums.length ; i++) {
System.out.println(nums[i]);
}
//输出数组的值
for (int num : nums) {
System.out.println(num);
}
}
数组做为参数
//输出数组的值
static void out(int[] array){
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
public static void main(String[] args) {
int[] nums=new int[4];
nums[0]=1;
nums[1]=2;
nums[2]=3;
nums[3]=4;
out(nums);
}
数组做为返回值
//反转数组
static int[] numbers(int[] array){
int[] arrays=new int[array.length];
for (int i = 0,j=arrays.length-1;i <array.length ; i++,j--) {
arrays[j]=array[i];
}
return arrays;
}
public static void main(String[] args) {
int[] nums=new int[4];
nums[0]=1;
nums[1]=2;
nums[2]=3;
nums[3]=4;
int[] numbers=numbers(nums);
//前面定义了一个输出数组的方法out(int[] array)
out(numbers);
}
多维数组
多维数组可以看成数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组
二维数组
语法
//数据类型[][] 变量名=new 数据类型[m][n];
//m表示这个二维数组有多少个数组
//n表示每一个一维数组的元素个数
int[][] arr=new int[3][2];
//定义了一个二维数组arr
//这个二维数组有3个一维数组,名称是ar[0],arr[1],arr[2]
//每个一维数组有2个元素,可以通过arr[m][n]来获取
多维数组的实例:
public static void main(String[] args) {
int a[][]={{1,2},{2,3}}; //创建一个多维数组
//{1,2} 这个下标为0 {2,3} 这个下标为1
//a[0][0] 前面那个0为数组的下标为0 第二个0是取得值是第一个
System.out.println(a[0][0]);
System.out.println(a[0][1]);
System.out.println(a[1][0]);
//a的数组只有两个长度,因为他们{1,2}是一个整体
System.out.println(a.length); //2
//a的0下标里面有两个数
System.out.println(a[0].length);//2
//循环外围的两个整体
for (int i = 0; i <a.length ; i++) {
//循环整体里面的两个数
for (int j = 0; j < a[i].length; j++) {
System.out.println(a[i][j]); //取出整体里面的值
}
}
}
Arrays数组
Arrays.sort() 升序排列
Arrays.toString() 数组以字符串的形式输出
Arrays.equals() 比较两个数组的值是否相同
Arrays.binarySearch() 使用二进制搜索算法搜索指定值的指定字节数组
Arrays.copyOfRange() 将指定数组的指定范围复制
int[] arrays=new int[]{1,2,7,4,68,5,4};
//把数组转换成字符串输出
System.out.println(Arrays.toString(arrays));
//将数组从小到大排序
Arrays.sort(arrays);
//输出排序好的数组
//注意点
//如果是数值,sort默认按照升序从小到大
//如果是字符串,sort默认按照字母的升序
System.out.println(Arrays.toString(arrays));
int[] arrays1={1,2,7,4,68,5,4};
Arrays.sort(arrays1);
//比较数组的值是否相等
//两个数组以相同的顺序包含相同的元素,则它们是相等的
//如果两个数组引用都是null,则它们被认为是相等的
System.out.println(Arrays.equals(arrays,arrays1));
Arrays.sort(arrays1);
//a - 要搜索的数组
//key - 要搜索的值
//使用二进制搜索算法搜索指定值的指定字节数组
// 在进行此调用之前,数组必须按照sort(byte[])方法进行排序。
// 如果没有排序,结果是未定义的。 如果数组包含具有指定值的多个元素,则不能保证将找到哪个元素。
System.out.println(Arrays.binarySearch(arrays1,68));
//将指定数组的指定范围复制到新数组中
//from - 要复制的范围的初始索引(包括)
//to - 要复制的范围的最终索引,排他。 (该索引可能位于数组之外)
int[] arrays2=Arrays.copyOfRange(arrays1, 0, 4);
System.out.println(Arrays.toString(arrays2));
冒泡排序
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成
算法
冒泡排序算法的原理如下:
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数
- 针对所有的元素重复以上的步骤,除了最后一个
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
public static void main(String[] args) {
//创建一个数组
int[] arr=new int[]{2,5,1,3,2};
//调用下面写的静态方法 传入数组的参数 并创建一个数组接受它
int[] arr1=sort(arr);
//通过Arrays的数组工具类来给数组输出值
System.out.println(Arrays.toString(arr1));
}
//冒泡排序的方法(降序 从大到小)
static int[] sort(int[] arr){
//循环比较的次数 五个数只需要比较四次
for (int i = 0; i < arr.length-1; i++) {
//循环比较相邻两个数的大小 把大的数放到前面 小的数在后面
for (int j = 0; j <arr.length-1-i ; j++) { //arr.length-1-i 每次数组最后的值都是最小的,就可以减去一次循环,没必要比了
//判断相邻后面的数比前面的数大的时候
if (arr[j+1]>arr[j]){
//创建一个临时变量,把小的给temp
int temp=arr[j];
//把大的给到前面
arr[j]=arr[j+1];
//把小的temp给到后面
arr[j+1]=temp;
}
}
}
//返回排序好的数组
return arr;
}
稀疏数组
稀疏数组可以看做是普通数组的压缩,但是这里说的普通数组是值无效数据量远大于有效数据量的数组
刚说到稀疏数组是一种压缩后的数组,为什么要进行压缩存储呢?
- 原数组中存在大量的无效数据,占据了大量的存储空间,真正有用的数据却少之又少
- 压缩存储可以节省存储空间以避免资源的不必要的浪费,在数据序列化到磁盘时,压缩存储可以提高IO效率
把二维数组变成稀疏数组
步骤:
-
创建一个二维数组
-
//数据类型[][] 变量名=new 数据类型[m][n]; //m表示这个二维数组有多少个数组 //n表示每一个一维数组的元素个数 -
随便给几个坐标附上附上值,下标从0开始
-
打印出这个数组的所有值(看看有哪些)
-
获取这个数组里面的有效值,不然所有的值都为0
-
创建一个稀疏数组(多少个数组是有效值+1,长度则是3)
-
判断不为0的数,给这个稀疏数组赋值
-
输出稀疏数组
把稀疏数组变成二维数组
步骤:
-
创建一个稀疏数组(它的长度为二维数组的行和列)
-
//数据类型[][] 变量名=new 数据类型[m][n]; //m表示这个二维数组有多少个数组 //n表示每一个一维数组的元素个数 -
循环把有效值赋值给二维数组的坐标上(坐标为稀疏数组的行和列)
-
输出还原的二维数组
完整代码
public static void main(String[] args) {
//创建一个二维数组 11*11
int[][] arr=new int[11][11];
//给数组的第二行的第三个数赋值1
arr[1][2]=1;
//给数组的第三行的第四个数赋值2
arr[2][3]=2;
System.out.println("输出原始数组");
//循环输出数组里面的值
for (int[] ints : arr) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
//当循环出一个数组时换行
System.out.println();
}
//转换为稀疏数组保存
//获取有效值的个数
int sum=0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
if(arr[i][j]!=0){
sum++;
}
}
}
System.out.println("有效值为"+sum);
//创建一个稀疏数组的数组 sum+1确定有多少个有效数需要存放(包括二维数组的行和列)
int[][] arr1=new int[sum+1][3];
//给数组的第一行的第一个数赋值11
arr1[0][0]=11;
//给数组的第一行的第二个数赋值11
arr1[0][1]=11;
//给数组的第一行的第三个数赋值
arr1[0][2]=sum+1;
//创建一个临时的变量 计算有多少个有效值的坐标赋值
int count=0;
for (int i = 0; i < arr.length; i++) {
//循环输出arr里面的值
for (int j = 0; j < arr.length; j++) {
if(arr[i][j]!=0){
count++;
//给数组的第count行的第一个数赋值i
arr1[count][0]=i;
//给数组的第count行的第一个数赋值j
arr1[count][1]=j;
//给数组的第count行的第一个数赋值arr[i][j]
arr1[count][2]=arr[i][j];
}
}
}
//输出获取有效值的数组
System.out.println("稀疏数组:");
System.out.println("行\t列\t有效值");
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j <arr1.length ; j++) {
System.out.print(arr1[i][j]+"\t");
}
System.out.println();
}
//把稀疏数组还原成二维数组
//给创建的数组给它赋值行和列
int[][] arr3=new int[arr1[0][0]][arr1[0][1]];
//值从1开始循环 不然下标的坐标越界
for (int i = 1; i < arr1.length; i++) {
//把arr1的[i][2]值赋给arr3[arr1[i][0]][arr1[i][1]]的坐标上
arr3[arr1[i][0]][arr1[i][1]]=arr1[i][2];
}
//循环输出数组里面的值
System.out.println("还原的二维数组:");
for (int[] ints : arr3) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
//当循环出一个数组时换行
System.out.println();
}
}

浙公网安备 33010602011771号