javaEE_day04☞java数组学习整理

理解数组

数组也是一种数据类型, 它本身是一种引用类型
1.什么是数组:存储相同数据类型的容器

2.特点

Java 的数组既可以存储基本类型的数据 ,也可以存储引用类型的数据,只要所有的数组元素具有相同的类型即可
有序的(下标,从0开始);
一旦数组的初始化完成,数组在内存中所占的空间将被固定下来,因此数组的长度将不可改变。 (属性 length)即使把某个数组元素的数据清空 ,但它所占的空间依然被保留 ,依然属于该数组,数组的长度依然不变。

定义数组

数据元素的类型[] 数组名;
int[] nums;
int nums[];

数组是一种引用类型的变量, 因此使用它定义一个变量时,仅仅表示定义了一个引用变量( 也就是定义了一个指针),这个引用变量还未指向任何有效的内存, 因此定义数组时不能指定数组的长度。 而且由于定义数组只是定义了一个引用变量,并未指向任何有效的内存空间 ,所以还没有内存空间来存储 数组元素,因此这个数组也不能使用,只有对数组进行初始化后才可以使用

创建数组(申请内存)

只要为数组元素分配了内存空间,数组元素就有了初始值。
数组的初始化有如下两种方式。

静态初始化: 初始化时由程序员显式指定每个数组元素的初始值,由系统决定数组长度。
动态初始化:初始化时程序员只指定数组长度,由系统为数组元素分配初始值。

1. 静态初始化
静态初始化的语法格式如下:

arrayName = new type[] {el ementl, element2 , element3 , element4 .. . } 

除此之外,静态初始化还有如下简化的语法格式:

type[] arrayName = {elementl, element2, element3, element4 . . . } 

2. 动态初始化
动态初始化的语法格式如下:

arrayName = new type[length] ;

数组初始化完成后,就可以使用数组了 ,包括为数组元素赋值、访问数组元素值和获得数组长度等。

存放数据

// 为 nums 的第一个数组元素赋值 
nums[0]=1;
nums[9]=2;

使用数组

// 输出 nums 数组的第1个元素
System.out.println(nums[0]);

for(int i=0;i<nums.length;i++){
    System.out.println(nums[i]);
}

增强for循环(foreach 循环)

for(int i : nums){
System.out.println(i);
}

//数组变成字符串
Arrays.toString(nums);

        int nums[];
		nums=new int[10];
		nums[0]=1;
		nums[9]=2;
		//数组变成字符串
		System.out.println(Arrays.toString(nums));    //[1, 0, 0, 0, 0, 0, 0, 0, 0, 2]
		for(int i=0;i<nums.length;i++) {
			//对数组中的元素赋值
			nums[i]=90;
			System.out.println(nums[i]);    //结果为10个 90
		}
		//测试数组中的元素是否真的被赋值
		System.out.println("aaa"+nums[2]);    //aaa90,所以这种写法可给数组元素赋值
		
		for(int n:nums) {
			n=80;
			System.out.println(n);   //结果为10个 80
		}
		System.out.println("未被赋值"+nums[2]);   //未被赋值0

从上面程序看, 当使用 foreach 来迭代访问数组元素时, foreach 中的循环变量相当于一个临时变量, 系统会把数组元素依次赋给这个临时变量,而这个临时变量并不是数组元素, 它只是保存了数组元素的值。因此,如果希望改变数组元素的值,则不能使用这种 foreach 循环

main方法的args数组的使用

public static void main(String[] args) {
		//练习:求数组元素的和
		//Integer.parseInt(args[i]);
		int sum=0;
		for(int i=0;i<args.length;i++) {
			int n=Integer.parseInt(args[i]);
			sum+=n;
			System. out .println(n+" ");
		}
		System. out .println("求和为:"+sum);
		//System. out .println(Arrays.toString(args)); 
	}

结果如下

1 
2 
3 
4 
求和为:10

数组的拷贝和扩容

Arrays.toString(type[] a): 该方法将一个数组转换成一个字符串.

        int [] a= {1,2,3,4,5};
		int [] b= new int[10];
		//数组的拷贝
		//b= {1,2,3,0,0......};
		//arraycopy
	    //第一个参数:原数组
		//第二个参数:原数组元素的起始位置
		//第三个参数:目标数组
	    //第四个参数:目标数组元素的起始位置
		//第五个参数:长度
	//	System.arraycopy(a, 0, b, 0, 3);
	//	System.out.println(Arrays.toString(b));
		
		//练习:b={0,0,3,4,0...}
		System.arraycopy(a, 2, b, 2, 2);
		System.out.println(Arrays.toString(b));

数组扩容(实际创建了一个新的数组),具体看下图

        //数组扩容(实际创建了一个新的数组)
		//copyOf
		//第一个参数:原数组(拷贝)
		//第二个参数:扩容之后的长度
		String[] names= {"张三"};
		names[1]= "李四";
		// 访问数组元素指定的索引值等于数组长度,所以下面代码将在运行时出现异常 
		System.out.println(names[1]);

如果访问数组元素时指定的索引值小于 0, 或者大于等于数组的长度,编译程序不会出现任何错误, 但运行时出现异常: java.lang.ArrayIndexOutOtBoundsException: N (数组索引越界异常),
在这里插入图片描述

       names=Arrays.copyOf(names, names.length+1);
       names[1]="李四";
       //结果为[张三, 李四]
   System.out.println(Arrays.toString(names));

在这里插入图片描述

内存:堆,栈 ,方法区,本地方法栈,寄存器
栈存局部变量,引用变量
堆存对象
jvm的线程垃圾回收

为什么有栈内存和堆内存之分?
当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块内存栈里,随着执行方法的结束,这个方法的内存栈也将自然销毁。因此,所有在方法中定义的局部变量都是放在栈内存中的;在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用,这个运行时数据就是堆内存。堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用,则这个对象不会被销毁。只有当一个对象没有任何引用变量引用它时,系统的垃圾回收器才会在合适的时候回收它。

提示:看待一个数组时, 一定要把数组看成两个部分:一部分是数组引用,也就是在代码中定义的数组引用变量;还有一部分是实际的数组对象,这部分是在堆内存里运行的,通常无法直接访问它,只能通过数组引用变量来访问 。

数组元素的排序

1.冒泡排序
两两比较,大的沉下去,小的浮上来,从小到大
在这里插入图片描述
图片来自这里.

例题:对23,56,22,15排序
第一轮排序
结果为23,22,15,56。交换了3次
过程如下

 23,56
     22,56
         15,56        

第二轮排序
结果为22,15,23,交换了2次
过程如下

 22,23
     15,23

第三轮排序
结果为15,22。交换了1次

用Java代码实现:

		int[] num= {23,56,22,15};
		int x;
        //进行了三轮排序
		for(int i=0;i<3;i++) {
		    //交换次数
			for(int j=0;j<num.length-1-i;j++) {
				if(num[j]>num[j+1]) {
					x=num[j];
					num[j]=num[j+1];
					num[j+1]=x;
				}
			}
		}
		//结果为[15, 22, 23, 56]
		System.out.println(Arrays.toString(num));

2.选择排序
在这里插入图片描述
用Java代码实现:

        for(int i=0;i<num.length-1;i++) {
			for(int j=i+1;j<num.length;j++) {
				if(num[i]<num[j]) {
					int x=num[i];
					num[i]=num[j];
				}
			}
		}
		System.out.println(Arrays.toString(num));

除上述之外,排序的方法Arrays.sort(num);也可以排序。

二维数组

1.声明
int[][] arrays;
//第一个[] 表示行,第二个表示列
int[] arrays[];
int arrays[][];

int[] a[],b;   //a二维,b一维.两者不包含
int[] c=new int[2];
int [][] d=new int[2][3];
//只有相同数据类型才能赋值

a=c;    //二维数组赋给一维数组   error
b=c;    //ok
a=d;    //error,因为a只是声明,d有指向内存
                     b=d;    //error   ??????
a[0]=c;  //a是二维,但是a[0]代表第一行,是一维数组
a[0]=d;  //error

2.创建
arrays=new int[2][3];//2行3列

3.赋值
arrays[0][2]=1;
结果为:

0 0 1
0 0 0

获取数组元素,使用嵌套循环

//二维数组名.length得到的是二维数组的行
		int[][] nums;
		nums=new int[2][3];
		nums[1][1]=1;
		for(int i=0;i<nums.length;i++){
		    for(int j=0;j<nums[i].length;j++){
		         System.out.print(nums[i][j]+"\t");
		     }
		    System.out.println();
		}

结果为:

0	0	0	
0	1	0

二维数组的其他定义方式:

//二维数组的其他定义方式
		int[][] nums=new int[2][3];
		int[][] nums2= {{1,2,3},{4,5,6}};
		int[][] nums3=new int[][]{{1,2,3},{4,5,6}};

不规则的二维数组的定义

        //int[][] nums=new int[][3];    error
		//int[][] nums=new int[][];   error
		int[][] nums=new int[3][]; //3行
		nums[0]=new int[3];
		nums[1]=new int[1];
		nums[2]=new int[5];
		for(int i=0;i<nums.length;i++){
		    for(int j=0;j<nums[i].length;j++){
		         System.out.print(nums[i][j]+"\t");
		     }
		    System.out.println();
		}

结果为:

0	0	0	
0	
0	0	0	0	0	

练习题

1.对角线求和
1 2 3 1 [0][0] 3 [0][2]
1 2 2 2 [1][1] 2 [1][1]
3 2 2 2 [2][2] 3 [2][0]

   public static void test() {
		int[][] nums=new int[][]{{1,2,3},{1,2,2},{3,2,2}};
		int sum=0;
		for(int i=0;i<nums.length;i++){
		    for(int j=0;j<nums[i].length;j++){
		    	if(i==j||i+j==2) {
		    		sum+=nums[i][j];
		    	}
		     }
		}
		System.out.print(sum);
	}

2.矩阵转置
1 2 3 [0][0] [0][1] [0][2]
4 5 6 [1][0] [1][1] [1][2]

1 4 [0][0] [0][1]
2 5 [1][0] [1][1]
3 6 [2][0] [2][1]

public static void test4() {
	int[][] nums=new int[][]{{1,2,3},{4,5,6}};
	int[][] nums2=new int[3][2];
	for(int i=0;i<nums.length;i++){
	    for(int j=0;j<nums[0].length;j++){
	    	nums2[j][i]=nums[i][j];	
	     }
	}
	for(int i=0;i<nums2.length;i++){
	    for(int j=0;j<nums2[i].length;j++){
	         System.out.print(nums2[i][j]+"\t");
	     }
	    System.out.println();
	}
	
}

3.杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1

public static void test3() {
	Scanner sc=new Scanner(System.in);
	System.out.println("input n:");
	int n =sc.nextInt();
	int[][] nums = new int[n][];
	for(int i=0;i<nums.length;i++){
		nums[i]=new int[i+1];
	    for(int j=0;j<nums[i].length;j++){
	    	if(j==0||i==j) {
	    	nums[i][j]=1;
	    	}else {
	    		nums[i][j]=nums[i-1][j-1]+nums[i-1][j];
	    	}
	     }  
	}
	for(int i=0;i<nums.length;i++){
	    for(int j=0;j<nums[i].length;j++){
	         System.out.print(nums[i][j]+"\t");
	     }
	    System.out.println();
	}
}

特点:每一行的开始和结束都是1;其余位置的元素是计算:
arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];
输入一个数字n表示行数,输出对应的前n行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值