【JAVA】第五章 方法与数组---数组

本文详细介绍了Java中的数组,包括数组的基本概念、动态和静态初始化方式、二维数组的声明、数组访问、异常处理(如索引越界和空指针异常)、内存分析以及常见的数组操作如遍历、获取最值、元素交换和冒泡排序。此外,还讨论了Java数组的不可扩容性和扩容策略。
摘要由CSDN通过智能技术生成

第五章 方法与数组–数组

5.2 数组

5.2.1 数组基本概念

1. 基本概念
1.数组:集中存储一定量相同类型数据的容器,是一个连续的内存空间
2. 数组有一维数组,二维数组,n维数组
二维数组:一维数组里面继续保存数组,每一个值都是一个一维数组
3.特点:
    (1)存储数据长度固定的容器, 数组是一个定长容器, 当定义一个数组时, 必须指定数组的长度(可为0) ,长度指定之后不可以更改
    (2)要存储的数据的数据类型要一致
4. 数组解决了相关多个变量多次声明的繁琐
2. 数组动态初始化
1.数组动态初始化: 只指定数组长度不指定数组元素值. (只声明,不初始化)
2.数组的声明: 
       (1)数据类型[] 数组名称 = new 数据类型[数组长度]; 
       int [ ] arr = new int[10];    //长度为10的int类型数组  ,数组中可以存储10个int类型数据
       
       (2)数据类型 数组名称[] = new 数据类型[数组长度]; 
        int  arr[ ] = new int[10];    //长度为10的int类型数组  ,数组中可以存储10个int类型数据
       
3.详细解释: 
(1)数据类型: 指定创建的数组容器可以存储的数据类型
(2)[]: 表示数组
(3)数组名称: 数组本身也是一个变量,用于存储数组的地址的变量名,就是引用,需要遵循标识符的命名规则
(4) = : 赋值符号,将数组的内存空间地址,赋值给数组名称(就是引用)
(5) new: 关键字,创建数组使用的关键字,用于在堆内存中给数组(数组也是变量)开辟存储数据的连续空间
(6) 数据类型: 和前面的数据类型保持一致
(7)数组长度: 表示数组容器中可以存储多少个元素

     
4.当定义出一个数组时, JVM虚拟机会默认为数组中的每一个元素进行默认的赋初值动作, 根据不同数据类型赋初值。
(1)整型 : 0
(2)浮点类型 : 0.0
(2)char类型 : ‘ ’
(4)boolean类型 : false
(5)引用数据类型 : null, null表示引用数据类型为空
        
public class Demo01 {

    public static void main(String[] args) {
        //动态数组的两种初始化方式
        int[] arr0 = new int[10]; //最常见的定义方式
        int arr1[] = new int[10];  //new 在堆内存中开辟空间
        System.out.println(arr0);
    }
}
3. 数组静态初始化
1.数组静态初始化: 在创建数组时,直接定义数组同时初始化数组存储的值(声明+初始化)
2.格式: 
   (1)数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, ..., 元素n};
   (2)简化格式: 数据类型[] 数组名 = {元素1, 元素2, ..., 元素n};
   (3)数据类型[][] 数组名称 = {{数组1},{数组2}......}
       int [][] arr ={{1,2,3},{3,4,5}};    //长度为2的int类型二维数组  ,数组中存储2个int类型一维数组
3.注意事项: 
  1)在第二个方括号中,不能写数组元素个数
  2)元素值的罗列:元素和元素之间,使用逗号分隔
  3)罗列出来的元素值,数据类型必须和声明数组时数据类型一致
 4)不能分成两行写,测试:先定义后赋值!不符合Java中定义数组的语法结构
class Demo01 {
 public static void main(String[] args) {
        int[] arr1 = new int[]{11,67,11,0,3};
        int[] arr0 = {334,11,67,11,0,3};
         }
 }
4. 二维数组的声明
二维数组声明方式灵活,常见声明方式有4种

在这里插入图片描述

(1)方式1
数据类型 数组名[][] = {{初始值1},{初始值2},{初始值3}}

public class Arr {
    public static void main(String[] args) {
    //定义一个二维数组
        int arr[][] = {{1,2,3},{4,5,6},{7,8,9}};
        //遍历二维数组
        for(int i=0;i<arr.length;i++){
            for(int j=0;j<arr[i].length;j++){
                System.out.print(arr[i][j]+" ");
            }
        }
    }
}

在这里插入图片描述

(2)方式2
(3)方式3
(4)方式4
5. 数组的访问格式
1.索引: 每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引,注: 索引也称为下标,角标,脚标。
2. 可以通过数组的索引访问到数组中的元素.索引的范围: 0---数组长度-1.
3.索引访问数组中的元素:
   数组名[索引] = 数值; //为数组中的元素赋值
   变量 = 数组名[索引]; //获取出数组中的元素

class Demo01 {
 public static void main(String[] args) {
     int[] arr = {334,11,67,11,0,3};
     arr[2] = 3;
     System.out.println(arr[2]);
         }
 }

5.2.2 数组的异常

2.2.1 索引越界
1..索引越界异常(数组下标越界):
   ArrayyIndexOutOfBoundsException
   数组 索引 超出     边界   异常
2.发生索引越界异常原因: 
      使用的索引在数组中不存在
3.代码分析: 
观察一下代码,运行后会出现什么结果
    class Demo01 {
     public static void main(String[] args) {
         int[] arr = {334,11,67,11,0,3};
         System.out.println(arr[7]);
     }
    }
创建数组,赋值3个元素,数组的索引就是0,1,2,没有3索引,因此我们不能访问数组中不存在 将会抛出 ArrayIndexOutOfBoundsException 数组越界异常.在开发中,数组的越界异常

4.越界异常避免方案
不要访问不存在的索引,使用索引时,验证索引在"0--数组长度-1"范围

5.数组的长度属性: 每个数组都具有长度,Java中赋予了数组一个属性,用于获取数组的长度arr.length

2.2.2 空指针异常
1.空指针异常
        NullPointerException
        空 指针 异常
2.发生空指针异常原因: 
    当引用数据类型值设置为null(前提),证明这个变量引用没有指向任何堆内存地址,但仍然想取出变量值
    注: null,即为空,用于表示在栈内存的引用中,不记录任何堆内存的地址
3.代码分析:
观察一下代码,运行后会出现什么结果
class Demo01 {
 public static void main(String[] args) {
     int[] arr = {334,11,67,11,0,3};
     arr = null;
     System.out.println(arr[7]);
 } 
}

17 arr = null这行代码,意味着变量arr将不会再保存数组的内存地址,也就不允许再操作数组了,
18 因此运行的时候会抛出NullPointerException 空指针异常.在开发中,数组的越界异常是不能出
19
20 4.空指针异常避免方案
21 在使用引用之前,先判断该引用的值是否为null,不为null再去访问

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5AWWmmua-1638090027190)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20211123215034061.png)]

5.2.3 数组的内存分析

1. Java的内存划分和作用
1.内存概念: 内存是计算机中的重要原件,临时存储区域,作用是运行程序.我们编写的程序是存放 必须放进内存中才能运行.
2.Java虚拟机的内存划分Java虚拟机要运行程序,对空间进行了不同区域的划分,因此每一片区域都有特定的处理数据。

在这里插入图片描述

2. 数组在内存中的存储
1. 声明的变量在栈中
2. 数组值存储在堆中,拥有连续的内存空间,有自己的内存地址
3. 索引(数组名指向内存地址)

在这里插入图片描述

01 1个一维数组的内存图
1.数组引用的是数组值的内存存储地址,是数组在内存中的地址.new出来的内容,都是在堆内存中存储的。

在这里插入图片描述

02 2个一维数组的内存图
两个数组:引用数据类型每次new,都在内存中开辟新的空间地址.地址之间没有联系。

在这里插入图片描述

03 两个引用指向同一个一维数组空间
多个引用指向同一个数组空间:任意一个引用修改了数组中的内容,其他引用访问到的就是修改后的数据

在这里插入图片描述

class Demo01 {
 public static void main(String[] args) {
     int[] arr = new int[3];
     arr[0] = 18;
     arr[1] = 9;
     int[] arr1 = arr; //把arr的引用赋值给arr1
     System.out.println(arr1[0]);
     System.out.println(arr1[1]);
     System.out.println(arr1[2]);
 }
}
04 二位数组的内存空间

在这里插入图片描述

1. 二维数组里的每一个一维数组都有自己的内存空间地址,并且多个一维数组的内存地址是连续的,所以使用一个总地址代表所有一维数组内存地址集合
2. 访问某个数据,先指定它所在一维数组在二维数组中的索引,再指定数据在一维数组中的索引,和矩阵差不多的理解

5.2.4 数组常见操作

1.遍历数组元组
1.数组遍历: 就是将数组中的每个元素分别获取出来,这就是遍历
2.分析思路: 
        通过循环,访问到数组中所有元素的索引,0到lenght-1
        通过索引,访问到对应元素,数组名[索引]
public class Demo01 {
    //遍历数组

    public static void main(String[] args) {
        int[] arr = {2,7,88,4,45,0}; //索引有0,1,2,3,4,5
        for(int i = 0;i < arr.length - 1;i ++) {
            System.out.println(arr[i]);
            }
        }
}
2.4.2 数组获取最值
1.给定一个数组,求出数组的最大值
2.分析思路(擂台思想):
        1)定义变量,保存数组0索引上的元素
        2)遍历数组,获取出数组中的每个元素
        3)将遍历到的元素和保存数组0索引上值的变量进行比较
        4)如果数组元素的值大于了变量的值,变量记录住新的值
        5)数组循环遍历结束,变量保存的就是数组中的最大值

😁擂台思想:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-shYepipi-1638090027197)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20211123225032339.png)]

import java.util.Arrays;

public class Demo01 {
    //数组元素取最值

    public static void main(String[] args) {
        int[] a = {2,7,88,4,45,0}; //索引有0,1,2,3,4,5
        int sum = a[0];
        for(int i = 1;i < a.length - 1;i ++) {
            if(a[i] > sum) {
                sum =a[i];
            }
        }

        System.out.println(sum);
    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-imyabJoG-1638090027199)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20211123172328399.png)]

2.4.3 数组元素交换
1.将数组中指定索引的两个元素交换位置. 
2.分析思路: 
        1)将两个索引位置对应的元素值获取到
        2)设计一个临时变量,先存储小索引元素的原值
        3)大索引元素值赋值给小索引元素位置
        4)临时变量值赋值给大索引元素位置
        int [] arr = {2,7,88,4,45,0}; 9
        要求:把88和 0 交换一下位置 打印数组
import java.util.Arrays;

public class Demo01 {
    //数组元素交换88 与0

    public static void main(String[] args) {
        int[] a = {2,7,88,4,45,0}; //索引有0,1,2,3,4,5
        int temp = a[2];
        a[2] = a[5];
        a[5] = temp;
        System.out.println(Arrays.toString(a));//遍历打印出数组a的元素
    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L5ufJSaH-1638090027200)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20211123171942322.png)]

2.4.4 冒泡排序😁
1.目标: 通过冒泡排序算法将数组中的元素进行升序或者降序排序
2.原理: 比较两个相邻的元素,将值大的元素交换至右端
3.思路: 
依次比较相邻的两个数,将小数放在前面,大数放在后面。
😂即在第一趟:首先比较第1个和第将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。
😁:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的
如此下去,重复以上过程,直至最终完成排序。
 ...
4.代码思路
用二重循环实现,外循环变量设为i,内循环变量设为j。假如有n个数需要进行排序,则外循每次进行比较的两个元素都是与内循环j有关的,它们可以分别用a[j]和a[j+1]标识
import java.util.Arrays;

public class Demo01 {
    //冒泡排序

    public static void main(String[] args) {
        int[] a = {2,7,88,4,45,0}; //索引有0,1,2,3,4,5
        int temp = 0;
        for(int m = 0;m < a.length - 1;m++) {
            //编写内循环,一趟
            for (int i = 0; i < a.length - 1 - m; i++) {
                if (a[i] > a[i + 1]) {
                    temp = a[i + 1];
                    a[i + 1] = a[i];
                    a[i] = temp;
                }
            }
        }

        System.out.println(Arrays.toString(a));//遍历打印出数组a的元素
    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MXRcNDEt-1638090027201)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20211123171702354.png)]

2.5数组的扩容

 Java数组扩容的原理
1)Java数组对象的大小是固定不变的,数组对象是不可扩容的。
2)利用数组复制方法可以变通的实现数组扩容。
3)System.arraycopy()可以复制数组。
4)Arrays.copyOf()可以简便的创建数组副本
5)创建数组副本的同时将数组长度增加就变通的实现了数组的扩容。
实际上此过程是废弃掉了旧的数组的地址,创建了新的数组,保留了原数组数据

案例:统计一个字符在字符串中的所有位置

import java.util.Arrays;

public class Demo01 {

    public static void main(String[] args) {
        char key = '是';//指定关键字
        String str = "罗滔是大猪蹄子吗?是滴!";//定义字符串
        System.out.println(str);
        //赋值调用 调用count方法count(参数名,参数名),赋值给count数组
        int[] count=count(str,key); //
        System.out.println(Arrays.toString(count));//遍历打印出数组count的元素
    }
    //编写count方法
    public static int[] count(String str ,char key) {
        int[] count = {}; //定义一个空数组count
        //for循环遍历比较 字符与key是否相等
        for(int i = 0;i < str.length();i ++) {
            char c = str.charAt(i); //把字符串第i个字符赋值给 c
            //条件语句比较 c与key
            if(c == key) {
                //数组扩容,复制原数组,增加长度,
             count = Arrays.copyOf(count, count.length + 1);
                //把位置值i赋值给count数组
             count[count.length - 1] = i;

            }
        }

        return count;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值