JAVA数组,自学笔记

文章所记载笔记内容均出自B站,尚硅谷讲师,宋红康老师视频!!!

JAVA数组

1.数组基本概念

  • 数组名
  • 下标
  • 元素
  • 长度

2.特点

  1. 数组作为应用数据类型,其引用放置于栈内存中,通过在堆内存开辟一条连续的存储空间来存储数据
  2. 数组本身是引用数据类型,数组中的元素可以是任何类型
  3. 初始化完成后,数组长度就确定了,不能更改,数组length为一个final常量
  4. 数组的toString()方法输出的是地址
  5. 数组元素的益处(数组越界)

3.一维数组的使用

3.1.数组的声明与初始化

       //静态初始化:变量的初始化与元素的赋值同时进行
        double[] prices1 = new double[]{20.2,30.0,40.0};
        //动态初始化:变量的初始化与元素的赋值分开进行
        double[] prices2 = new double[3];
        //其他正确的方式
        int arr1[] = new int[4];
        int[] arr2 = {1,2,3};

3.2.调用数组的指定元素

  • 元素下标index默认从0开始,其主要是代表内存地址的偏移量,例如第一个元素偏移量为0,所得内存地址就为数组元素的初始地址。
  • 元素下标的错误使用,系统会报出数组越界的错误

3.3.数组的属性:length

  • length表示数组的长度,在数组初始化时就已经确定,不能更改。其类型为final修饰的int常量

3.4.数组的遍历

  • 遍历超出length范围时会发生数组越界
        for(int i = 0 ; i < arr2.length ; i++){
            System.out.println(arr2[i]);
        }

3.5.数组元素的默认初始化值

  • 整型数组元素的默认初始化值:0
  • 浮点型数组元素的默认初始化值:0.0
  • 字符型数组元素的默认初始化值:0
  • boolean型数组元素的默认初始化值:false
  • 引用数据类型元素数组的默认初始化值:NULL
        int[] arr1 = new int[3];
        System.out.println(arr1[2]);

        double[] arr2 = new double[4];
        System.out.println(arr2[0]);

        char[] arr3 = new char[5];
        System.out.println(arr3[3]);

        boolean[] arr4 = new boolean[4];
        System.out.println(arr4[3]);

        String[] arr5 = new String[5];
        System.out.println(arr5[4]);

3.6.一维数组的内存解析

3.6.1.Java内存结构如何划分

请添加图片描述

区域名称作用
虚拟机栈用于存储正在执行的每个Java方法的局部变量表等。局部变量表存放了编译期可知长度
的各种基本数据类型,引用对象,方法执行完自动释放。
堆内存储存对象,new来创建的,都储存在堆内存当中。
方法区储存已被虚拟机加载的类的信息,常量,静态变量,即时编译器编译后的代码等数据。
本地方法栈当程序调用了native的本地方法(C的库)时,本地方法执行期间的内存区域
程序计数器程序计数器是CPU的寄存器,它包含每一个线程下一条要执行的指令地址。
3.6.2.一维数组的内存结构
  • 与目前数组相关的内存结构:

    int[] arr = new int[]{1,2,3} 为例

    • 虚拟机栈:用于存放方法中声明的变量 arr
    • 堆 :用于存放数组的实体(即数组元素){1,2,3}

请添加图片描述

4.二维数组的使用

从数组底层的运行机制来看,其实没有多维数组

4.1.数组的声明有初始化

        //静态与动态
        /*复习一维数组
        * int[] arr = new int[]{0,1,2};
        * int[] arr = new int[3];
        *int[] arr2 = {1,2,3};
        * */
        int[][] arr1 = new int[][]{{1,1},{2,2},{3,3,}};
        int[][] arr2 = new int[3][2];
		int[][] arr2 = new int[3][];
		int[][] arr1 = {{1,1},{2,2},{3,3,}};

4.2.数组元素的调用

		System.out.println(arr1[1]);
		//输出的结果为16进制地址

4.3.数组的长度

		System.out.println(arr1.length);
		//输出结果为3
		//当然二维数组不止本身有长度,其所包含的一维数组也是有长度的
		System.out.println(arr1[1].length);
		//输出结果为2

4.4.遍历数组

		//可以采用嵌套循环来完成
		for(int i = 0;i<arr1.length;i++){
            for(int j = 0;j<arr[i].length;j++){
                System.out.print(arr[i][j]);
            }
        }

4.5.数组元素的默认初始化值

4.5.1.默认初始化方式一

(int[][] ar1 = new int[3][4])

  • 外层元素,默认储存地址值
  • 内层元素默认与声明类型一致的基础值
  • 整型数组元素的默认初始化值:0
  • 浮点型数组元素的默认初始化值:0.0
  • 字符型数组元素的默认初始化值:0
  • boolean型数组元素的默认初始化值:false
  • 引用数据类型元素数组的默认初始化值:NULL
      int[][] ar1 = new int[3][4];
      System.out.println(ar1[2]);//[I@776ec8df
      System.out.println(ar1[1][2]);//0

      boolean[][] ar3 = new boolean[3][4];
      System.out.println(ar3[2]);//[Z@4eec7777
      System.out.println(ar3[1][2]);//false

      String[][] ar4 = new String[3][4];
      System.out.println(ar4[2]);//[Ljava.lang.String;@3b07d329
      System.out.println(ar4[1][2]);//null
4.5.2.默认初始化方式二

(int[][] ar2 = new int[3][])

  • 外层默认存储NULL值(内存元素未指定长度,系统不会开辟空间,内层没有地址,外层只能按引用数据类型的方式来处理,放置一个NULL值)
  • 内层元素不存在,如果调用系统报错,空指针异常
      int[][] ar4 = new int[3][];
      System.out.println(ar4[2]);//null
      System.out.println(ar4[2][3]);//NullPointerException 空指针异常

4.6.二维数组内存解析

请添加图片描述

请添加图片描述

4.7.二维数组课后练习

4.7.1.遍历求和

请添加图片描述

        //静态初始化
        int[][] arr1 = new int[][]{{3,5,8},{12,9},{7,0,6,4}};
        //动态初始化
        int[][] arr2 = new int[3][];
        arr2[0] = new int[]{3,5,8};
        arr2[1] = new int[]{12,9};
        arr2[2] = new int[]{7,0,6,4};
        //使用嵌套for循环来遍历二维数组
        int sum = 0;
        for (int i = 0; i < arr1.length ; i++) {
            for (int j = 0; j < arr1[i].length ; j++) {
                sum+=arr1[i][j];
            }
        }
        System.out.println(sum);
4.7.2.数组的赋值情况与处理方法

请添加图片描述

int[] x,y[];//表示 int[] x ; int[] y[]表示 === int[][] y;
// x 为整形的一维数组
// y 为整形的二维数组
  • x[0] = y; //错误,数组为引用类型,x[0]与y类型不一样,不可直接赋值
    
  • y[0] = x; //正确,y[0]表示int型一维数组(y表示二维数组),x也是int型一维数组
    
  • y[0][0] = x; //错误,类型不一样
    
  • x[0][0] = y; //错误,x不是二维数组
    
  • y[0][0] = x[0]; //正确,y[0][0]二维数组的内层元素就是一维数组
    
  • x = y ; //错误
    

5.数组中常见算法与操作

5.1.数组特征值计算

请添加图片描述

        //动态初始化创建数组
        int[] arr = new int[10];
        //for循环给数组赋值
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int)(Math.random()*90)+10;
            System.out.print(arr[i]+"\t");
        }
        System.out.println();
        //求最大值
        int max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            max=arr[i]>max?arr[i]:max;
        }
        System.out.println(max);
        //最小值
        int min = arr[0];
        for (int i = 0; i < arr.length; i++) {
            min=arr[i]<min?arr[i]:min;
        }
        System.out.println(min);
        //总和
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum+=arr[i];
        }
        System.out.println(sum);
        //平均值
        int avgsum = sum/arr.length;
        System.out.println(avgsum);

5.2.数组的赋值与复制

  • 创建一个长度为6 的int型数组,要求数组元素的值都在1-30之间,且都是随机赋值,同时要求各元素的值各不相同
        int[] arr = new int[6];
        for (int i = 0; i < 6; i++) {
            arr[i] = (int)(Math.random()*30)+1;
            for (int j = 0; j < i; j++) {
                if(arr[i]==arr[j]){
                    i--;
                    break;
                }
            }
        }
        for (int i = 0; i < 6; i++) {
            System.out.print(arr[i]+"\t");
        }

请添加图片描述

  • 直接将array2=array1这样做只会将数组 1 的地址值赋给数组 2
  • 数组2与数组1指向同一片内存空间
  • 当改变数组 2 的值时,也是改变数组1 的值
  • 如果需要完成值的复制,可以通过for循环将array1[x] = array[y]进行赋值来完成复制

5.3.数组元素的反转

请添加图片描述

方法一 : 新建一个数组来反转加复制(倒着遍历)

        int[] arr = {4,5,8,2,1,9};
        int[] arr2 = new int[6];
        for (int i = 0; i < 6; i++) {
            arr2[i] = arr[5-i];
        }
        arr = arr1;

方法二 : 从两端往里走,一组一组反转(长度为奇数与偶数两种情况在代码中都一样)

        int[] arr = {4,5,8,2,1,9,7};
        for (int i = 0; i < (int)((arr.length+1)/2) ; i++) {
            int temp = 0;
            temp = arr[i];
            arr[i] = arr[arr.length-1-i];
            arr[arr.length-1-i] = temp;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+"\t");
        }

方法三 :设置两个指针作用的标志,分别从两端往里走,当x=y || x>y时停止

        int[] arr = {4,5,8,2,1,9,7};
		int x = 0;
        int y = arr.length-1;

        while (x<y){
            int temp = 0;
            temp = arr[x];
            arr[x] = arr[y];
            arr[y] = temp;
            x++;
            y--;
        }

5.4.数组的扩容与缩容

因为数组一旦建立,其大小长度类型都不可改变,所以数组扩容与缩容原理相同,都是要新建一个数组,将老数组的值赋给新数组,同时将新数组的地址赋值给老数组,当老数组的内存不再被指定时,JAVA的GC机制会将老内存释放。

请添加图片描述

        //数组扩容
        int[] arr = new int[]{1,2,3,4,5};
        //扩容一倍
        int[] newArr = new int[arr.length*2];
        //或int[] newArr = new int[arr.length << 1];
        //将原来数组的元素复制到新数组
        for (int i = 0; i < arr.length; i++) {
            newArr[i] = arr[i];
        }
		arr = newArr;

5.5.数组的元素查找

请添加图片描述

5.5.1.线性查找
        int[] arr = new int[]{21,55,45,66,5,4,8,11};
        int target = 5;
        //线性查找
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == target){
                System.out.println("找到"+(i+1));
                break;
            }
            if(i == arr.length-1) System.out.println("未找到");
        }
5.5.2.二分法查找

使用二分法的要求:数组数值顺序排列

二分法概念解析

请添加图片描述

二分法程序流程解析

请添加图片描述

int[] arr2 = new int[]{1,3,5,7,9,11,22,32}
int h = 0;
int end = arr2.length-1;
int mid = (h+end)/2;
while(h <= end){
    mid = (h + end)/2;
    if (arr2[mid] == target){
        break;
    }else if (arr2[mid] > target){
        end = mid;
    }else {
        h = mid;
    }
}
System.out.println(arr2[mid]);

5.6.数组元素排序

5.6.1.冒泡排序

请添加图片描述

        int[] arr = {34,35,4,8,45,12,22,32,54,66};
        //冒泡排序
        int temp = 0;
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < arr.length-i; j++) {
                if (arr[j] > arr[j+1]){
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
5.6.2.快速排序

快速排序思想

请添加图片描述

//当end动的时候,head指向的值永远 <= arr[mid]
/*为什么要先从右边end开始往回走的问题 :
        右边开始end所经过的值都是比mid大的,当他停下来的时候其指向位置要么小于mid,要么指向与head相同(
        这时候end指向的值等于head等于mid,这也是为啥head最初指向要与mid相同)直接表示排序完成
        左边开始的话,head停下来有两种情况 :
            第一种----安全的 : head遇到比mid大的值,停下等待与end交换
            第二种----危险的 : head一直往右对比,知道遇到end指向的值停止,但是此时并没有对end指向的值与mid比大小
        程序中需要的就是当head与mid相遇时交换位置。
*/
public static void quickSort(int[] arr , int head , int end){
        //作为递归的出口
        //为什么是判断是 >= : 当end指针从后往前畅通无阻,一直遇到head时,head,end都是0,这时候参与递归的i-1作为end值就会比head小
        if(head >= end) {
            System.out.println("11111");
            return;
        }
        //第一步 : 给mid,i,j赋值
        int i = head;
        int j = end;
        int mid = head;
        int temp = 0;
        while (i < j){
            //第二步 : end从后往前找出小于arr[mid]的元素(或者相遇的情况下也要停下来,相遇的点一定小于arr[mid])
            while(arr[j] >= arr[mid] && i != j) j--;
            //第三步 : head从前往后走,找出大于arr[mid]的元素
            while(arr[i] <= arr[mid] && i != j) i++;
            //第四步 : 先判断i==j?如果相等直接与mid进行交换,如果不等就让i与j交换
            if (i == j){
                temp = arr[i];
                arr[i] = arr[mid];
                arr[mid] = temp;
                break;
            }else {
                temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }

        quickSort(arr,head,i-1);
        quickSort(arr,i+1,end);
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值