java ——数组
✍作者:电子科大不知名程序员
🌲专栏:java学习指导
各位读者如果觉得博主写的不错,请诸位多多支持;如果有错误的地方,欢迎在评论区指出
数组是一组相同类型元素按一定顺序排列的集合
数组相关的概念:
1.数组名
2.数组元素
3.数组的特点:数组是有序排列的
4.角标、下标、索引
数组的概述
1.数组属于引用数据类型的变量;数组的元素既可以是基本数据类型,也可以是引用数据类型;
2.数组的长度一旦确定以后就不能修改
3.数组的分类
—>按照维数:一维数组、二维数组…
—>按照数组元素的类型,基本数据类型元素的数组、引用数据类型元素的数组
一维数组的使用
1.一维数组的声明和初始化
int[]ids; //声明(ids为数组名),而int[]代表要创建一个int类型的数组
//静态初始化:数组的初始化和数组元素的赋值操作同时进行
ids=new int[]{1,2,3,4};
//动态初始化:数组的初始化和数组元素的赋值分开进行
String [] names=new String[5];
总结:数组一但初始化完成,其长度就确定了
2.如何调用数组的指定位置的元素:通过角标的方式调用
数组的角标从0开始,到数组的长度-1结束
3.如何获取数组长度:
属性:length
System.out.println(ids.length);
4.如何遍历数组
for(int i=0;i<ids.length;i++){
System.out.println("ids[i]");
}
5.数组元素的默认初始化值
—>数组元素是整型,默认初始化值为0;
—>数组元素是浮点型,默认初始化值为0.0;
—>数组元素是char型,默认初始化值为0或’\u0000’,而非’0’
—>数组元素是boolean型,默认初始化值为false;
—>数组元素是引用数据类型(String),默认初始化值为null;
6.数组的内存解析
内存结构的简单说明:
(放在方法中的变量叫做局部变量)
栈区&堆区
多维数组
1.二维数组的声明和初始化:
int[] arr=new int[]{1,2,3};
int[][] arr1=new int[][]{{1,2,4},{2,3,4},{3,4,5}}; //二维数组的静态初始化
动态初始化:
String[][] arr2=new String[3][2];
动态初始化时:必须要对行初始化,列不一定需要初始化
String[][] arr2=new String[3][2]; //right
赋值不带长度,带长度时不赋值
2.如何调用数组的指定位置的元素
//首先我们声明并初始化一个二维数组:
String[][] arr=new String[3][] //这里未对列进行初始化
//然后我们访问指定位置的元素
System.out.println(arr[1][1]); //null 这里就会出现空指针
我们这里只声明了有三行,因此在堆区生成了三行都是空的一个数组,未生成列
因此我们在第二行声明列即可:
arr[1]=new String[4];
System.out.println(arr[1][1]);
//这样就在这个数组的第二行生成了一个能存4个元素的新数组
3.获取数组的长度
int[][] arr1=new int[][]{{2,4},{2,3,4},{3,4,5}};
System.out.println(arr1.length); //3
arr1指的就是一个一维数组,只是这个一维数组的元素又是一个数组,所以才是二维数组
下面我们来研究这种情况:
System.out.println(arr[0].length); //代表arr数组保存的第一个元素{2,4}的长 2
System.out.println(arr[1].length); //{2,3,4} 3
4.如何遍历二维数组
public class Two_dimensional_Array_Traversal {
public static void main(String[] args) {
int[][] arr=new int[][]{{1,2},{1,2,3},{1,2,3,4}};
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();
}
}
}
5.二维数组的使用
规定:二维数组分为外层数组的元素,内层数组的元素
对于int型:
int[][] arr=new int[4][3]; //动态初始化
//外层元素:arr[0],arr[1] 等
//内层元素:arr[0][0],arr[1][2]等
public class Two_dimensional_Array_Initialization {
public static void main(String[] args) {
int[][] arr=new int[4][3];
System.out.println(arr[0]);
System.out.println(arr[0][0]);
}
}
运行结果如下:
我们因此可以看到:第一个初始化是地址,第二个才是0
这是怎么回事呢,因为在外层数组元素是数组,指向的是内层元素
对于float型:
System.out.println(arr[0]); //仍是地址值
System.out.println(arr[0][0]);//0.0
对于String型:
System.out.println(arr[0]); //地址值
System.out.println(arr[0][0]);//null
另一种初始化方式:
double[][] arr1=new double[4][];
System.out.println(arr1[0]); //null
System.out.println(arr1[0][0]);//报错:空指针异常
【总结】:对于初始化方式一,外层元素的初始化值为地址值,内层元素的初始化值与一维数组初始化情况相同;对于初始化方式二,外层元素的初始化值为null,外层元素的初始化值会报错:不能调用
6.二维数组的内存
栈空间保存arr1,右边是堆空间
实例:使用二维数组打印杨辉三角
public class Print_Yang_Hui_Triangle {
public static void main(String[] args) {
//声明并初始化数组
int[][] Triangle_Array=new int[10][]; //十行,但由于每一行的列数都不一样
//给数组元素赋值
//先搭建10行
for(int i=0;i<Triangle_Array.length;i++) { //这里通过.length来获取数组的长度
Triangle_Array[i]=new int[i+1]; //i是从0开始的,所以i所在的行其实有i+1列
//给首末元素赋值
Triangle_Array[i][0]=1;
Triangle_Array[i][i]=1;
//给其它元素赋值
if(i>1) {
for(int j=1;j<Triangle_Array[i].length-1;j++) {
Triangle_Array[i][j]=Triangle_Array[i-1][j-1]+Triangle_Array[i-1][j];
}
}
}
//遍历二维数组(打印出来)
for(int i=0;i<Triangle_Array.length;i++) {
for(int j=0;j<Triangle_Array[i].length;j++) {
System.out.print(Triangle_Array[i][j]+" ");
}
System.out.println();
}
}
}
【总结】:编写杨辉三角时我们需要明白,我们创建的二维数组并不是10*10的传统二维数组,而是每一行对于的列数都不相同,因此这里我们采用动态初始化的方式,来先确定行;然后到下一步我们来初始化数组的列,而对于列来说,i表示的行本质实在第i+1行,因此有i+1列,因此i对应行的来表示列的数组有i+1个元素;最后根据杨辉三角的规律给每一个元素赋值:每一行首元素和末元素都是1,剩余的遵循数学规律,而在自己做的时候忽略掉的一点就是其实可以用.length来计算数组的元素个数(即是数组的元素个数)
数组中涉及到的算法
1.数组元素的赋值
2.求数组值型元素中的最大值、最小值、平均数、总和等
public class Random_numbers_Compare {
public static void main(String[] args) {
//生成随机数
//公式:(int)(Math.random()*(99-10+1)+10)
int[] arr=new int[10];
for(int i=0;i<arr.length;i++) {
arr[i]=(int)(Math.random()*(99-10+1)+10);
}
//显示生成的随机数组
for(int i=0;i<arr.length;i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
//求最大值:
int maxValue=arr[0];//这里最好不要初始化为0,以防数组中的元素全是负数,这里让它为数组中任意一个元素即可
for(int i=0;i<arr.length;i++) {
if(maxValue<arr[i]) {
maxValue=arr[i];
}
}
System.out.println("最大值为:"+maxValue);
//求最小值
int minValue=arr[0];
for(int i=0;i<arr.length;i++) {
if(minValue>arr[i]) {
minValue=arr[i];
}
}
System.out.println("最小值为:"+minValue);
//求平均值
int sum=0;
for(int i=0;i<arr.length;i++) {
sum+=arr[i];
}
double averageValue=(sum*1.0)/arr.length;
System.out.println("平均值为:"+averageValue);
}
}
3.数组的复制
public class Copy_Arrays {
public static void main(String[] args) {
int[] array1,array2;
array1 =new int[]{2,3,5,7,11,13,17,19};
for(int i=0;i<array1.length;i++) {
System.out.print(array1[i]+" ");
}
System.out.println();
//赋值array2变量等于array1
//array2=array1; //对array1进行初始化后,new的堆空间地址赋值给array2
//上面的操作不能称为数组的复制,只是在栈空间的array1和array2指向同一块堆空间的地址(唯一的一个数组实体)
//若真正的实现array1到array2数组的复制:
array2=new int[array1.length];
for(int i=0;i<array2.length;i++) {
array2[i]=array1[i];
}
//修改偶索引元素的值使其等于其索引值
for(int i=0;i<array2.length;i++) {
if(i%2==0) {
array2[i]=i;
}
}
//遍历array1和array2
for(int i=0;i<array2.length;i++) {
System.out.print(array1[i]+" ");
}
System.out.println();
for(int i=0;i<array2.length;i++) {
System.out.print(array2[i]+" ");
}
}
}
4.数组的反转
public class Inversion_Arrays {
public static void main(String[] args) {
String[] arr=new String[] {"N","I","V","E","K"};
//数组的翻转
for(int i=0;i<arr.length/2;i++) {
String temp=arr[i];
arr[i]=arr[arr.length-1-i];//这里需要注意数组下标为arr.length-1代表的是最后一个元素
arr[arr.length-1-i]=temp;
}
//遍历
for(int i=0;i<arr.length;i++) {
System.out.print(arr[i]+" ");
}
}
}
【注意】:这里的数组翻转并不是反过来打印,而是要真正改变数组的元素的值;而第二个需要注意的是,在交换时循环条件的控制上并不能讲整个数组都遍历完,这样会交换一次后有交换回来,只用遍历到一半即可实现交换(对于奇数个偶数个都是一样的)
5.数组的查找:线性查找、二分法查找
public class Linear_Lookup {
//线性查找
public static void main(String[] args) {
String[] arr=new String[]{"N","I","V","E","K"};
String target="E";
boolean isFlag=true;
for(int i=0;i<arr.length;i++) {
if(target.equals(arr[i])) {
System.out.println("找到了指定元素,位置为:"+i);
isFlag=false;
}
}
//没有查找到时我们给予提示,但如果直接输出找到和未找到都会输出
//而且我们不能在循环内部添加,因为查找时一定要让循环走完
if(isFlag) {
System.out.println("未找到指定元素");
}
}
}
注意:target.equals(arr[i])
这里我们如果要比较整型数值的大小,直接使用==即可,而这里我们需要比较两个字符串是否相同,用到的语法为:
target.equals(arr[i]);
target和arr[i]是要比较的两串字符串
public class Dichotomy_Lookup {
//二分法查找
//前提:所要查找的数组必须有序
public static void main(String[] args) {
int[] arr=new int[] {-32,-15,-10,2,30,45,90}; //有序
int target=30;
//首索引和末索引
int left=0;
int right=arr.length-1;
boolean isFlag=true;
while(left<=right) {
int mid=(left+right)/2;
if(target==arr[mid]) {
System.out.println("找到了,元素的位置为:arr["+mid+"]");
isFlag=false;
break;
}
else if(target<arr[mid]){
right=mid;
}
else {
left=mid;
}
}
if(isFlag) {
System.out.println("未找到该元素");
}
}
}
6.数组的排序
例如我们在使用二分法时,要求数组是有序的,因此数组的排序意义重大
评价排序算法的优劣:时间、空间、稳定性
稳定性:若两个记录A和B关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的
排序的分类:外部排序和内部排序
冒泡排序:
public class Bubbling_Sorting {
public static void main(String[] args) {
//冒泡排序
int[] arr=new int[] {-12,22,45,-87,-22,56,78,23,-66};
for(int i=0;i<arr.length;i++) {
for(int j=0;j<arr.length-1-i;j++) {
if(arr[j]<arr[j+1]) {
int tem=arr[j];
arr[j]=arr[j+1];
arr[j+1]=tem;
}
}
}
for(int i=0;i<arr.length;i++) {
System.out.print(arr[i]+" ");
}
}
}
Arrays工具类
import java.util.Arrays;
public class Arrays_tool_class {
public static void main(String[] args) {
//1.boolean equals(int[] a,int[] b):判断两个数组是否相等
int[] arr1=new int[] {1,2,3,4};
int[] arr2=new int[] {1,3,2,4};
boolean isEquals=Arrays.equals(arr1, arr2);
System.out.println(isEquals); //false(数组是有顺序的)
//2.String toString(int[] a):输出数组信息
System.out.println(Arrays.toString(arr1)); //[1, 2, 3, 4]
//3.void fill(int[] a,int val):将指定值(val)填充到数组中
Arrays.fill(arr1, 10);
System.out.println(Arrays.toString(arr1)); //[10, 10, 10, 10]
//4.void sort(int[] a):对数组进行排序
Arrays.sort(arr2);
System.out.println(Arrays.toString(arr2)); //[1, 2, 3, 4]
//5.int binarySearch(int[],int key):二分查找(数组要先有序)
int[] arr3=new int[] {1,2,4,5,8};
int index=Arrays.binarySearch(arr3, 5);
System.out.println(index); //3 这个3代表的数组的下标
//若返回值为负数:没有找到
}
}