• 8.数组


    1.1 数组介绍

     数组(array)是一种容器,用来存储同种数据类型的多个值

    总结:数组容器在存储数据的时候,需要结合数据类型考虑。

    例如:int 类型的数组容器(boolean byte short double

    建议:容器的类型,和存储的数据类型保持一致

    数组容器的使用场景

    总结:如果今后要操作的数据,是同一组数据,就可以使用数组容器进行存储

    1.2.1 第一种格式

    数据类型[] 数组名

    示例:

    int[] arr;        
    double[] arr;      
    char[] arr;
    

    1.2.2 第二种格式

    数据类型 数组名[]

    示例:

    int arr[];
    double arr[];
    char arr[];
    
    public class Demo1Array {
        /*
        * 数据类型[] 数组名
        * 数据类型 数组名[]
        * */
        public static void main(String[] args) {
            //数据类型[] 数组名
            //定义了一个int类型的数组,数组名叫arr
    
            /*
            * 这里虽然是定义了一个数组,但也仅仅只是一个数组类型的【变量】,变量没有进行初始化
            * 就直接使用了,这就是错误原因
            *
            * */
            //int []arr=创建数组容器;
            //定义了一个char类型的数组,数组名叫cArr
            char[] cArr;
    
        }
    }
    

    1.3 数组的动态初始化

    数组初始化概述

    Java中的数组必须先初始化,然后才能使用

    所谓初始化:就是在内存中,维数组容器开辟空间,并将数据存入容器中的过程

    1.3.1 什么是动态初始化

    数组动态初始化就是只给定数组的长度,由系统给出默认初始化值

    1.3.2 动态初始化格式

    数据类型[] 数组名 = new 数据类型[数组长度];
    int[] arr = new int[3];
    

    例子:

    public class Demo2Array {
        //注意:打印数组变量的时候,会打印出数组的内存地址
    
        /*
        * [I@880ec60:
        *           @:分隔符
        *           [:当前的空间是一个数组类型
        *           I:当前数组容器中所存储的数据类型
        *           880ec60:十六进制内存地址
        *              0 1 2 3 4 5 6 7 8 9 a b c d e f
        * */
        public static void main(String[] args) {
            //数据类型[] 数组名 = new 数据类型[数组长度];
            //通过new 关键字创建了一个int类型的数组容器,该容器可以存储5个int类型的整数,
            //该容器被arr数组变量所记录
            int [] arr=new int[5];
            //[I@880ec60
            System.out.println(arr);
            byte[] bArr=new byte[3];
            //[B@3f3afe78
            System.out.println(bArr);
        }
    }
    

    1.4 数组元素访问

    数组内存地址的访问方式

    格式:数组名

    数组内部保存的数据的访问方式

    格式:数组名[索引]

    注意:int[] arrayA:这里仅仅是定义了一个可以存储一个int数组的变量而已,现在还没有具体的数组

    int[] arrayA:数组变量中保存数组在内存空间的地址值,通过该地址值就可以找到具体的数组

    理解:数组变量可以理解为门牌号,具体的数组可以理解为教室

    1.4.1 什么是索引

    索引是数组容器中空间的编号

    特征1:索引从0开始

    特征2:索引是连续的

    特征3:索引逐一增加,每次加1

    作用:访问数组容器中的空间位置

    public class Demo3ArrayIndex {
        /*
           数组动态初始化:
                   初始化的时候, 手动指定数组长度, 系统会为数组容器分配初始值.
           数组的元素访问格式:
                   数组名[索引]
                   索引: 数组中数据的编号方式, 编号从0开始
                   作用: 访问数组容器中的空间位置
           注意:
                   数组在创建完毕后, 即使没有赋值, 也可以取出, 但取出的元素都是默认初始化值.
        */
        public static void main(String[] args) {
            int [] arr=new int[3];
            System.out.println(arr);//数组的内存地址
            //数组名[索引] 访问数组容器中的空间位置
            System.out.println(arr[0]);   //0 系统自动分配的默认初始化值
            System.out.println(arr[1]);
            System.out.println(arr[2]);
            System.out.println("--------------");
            // 数组名[索引]
            arr[0] = 11;
            arr[1] = 22;
            arr[2] = 33;
            System.out.println(arr[0]);
            System.out.println(arr[1]);
            System.out.println(arr[2]);
        }
    }
    

    1.5 内存分配

    Java程序在运行时,需要在内存中分配空间。

    为了提高运算效率,就对空间进行了不同区域的划分

    每一篇区域都有特定的处理数据方式和内存管理方式

    Java中内存分配

    栈内存:方法运行时,进入的内存,局部变量都存放于这块内存当中

    堆内存:new出来的内容都会进入堆内存,并且会存在地址值

    方法区:字节码文件(.class文件)加载时进入的内存

    本地方法栈:调用操作系统相关资源,jvm在操作系统功能的时候使用

    寄存器:交给CPU去使用,和开发无关

     Java中内存分配

    整数 默认值0

    浮点数 默认值 0.0

    布尔 默认值 false

    字符 默认值 空字符

    引用数据类型 默认值 null

    引用数据类型:引用,记录了地址值的变量,所对应的数据类型,就是引用数据类型

    例如 int [] arr=new int[3];  

    public class Demo4Array {
        public static void main(String[] args) {
            int []arr1=new int[2];
            System.out.println(arr1);
            arr1[0]=11;
            arr1[1]=22;
            System.out.println(arr1[0]);
            System.out.println(arr1[1]);
            System.out.println("-------------");
            int[] arr2 = new int[3];
            System.out.println(arr2);
            arr2[0] = 33;
            arr2[1] = 44;
            arr2[2] = 55;
            System.out.println(arr2[0]);
            System.out.println(arr2[1]);
            System.out.println(arr2[2]);
        }
    }
    

      

    1.7 两个数组内存图

     注意:每new一次,在堆内存中,都是一块新的空间,堆内存中的空间地址不会出现重复的现象

    注意:

    1.数组名称保存数组在堆内存中的地址值

    2.通过数组名称找到堆内存中的具体数组,然后通过索引编号找到对应的具体的某个元素

    1.8 多个数组指向相同内存图

    public class Demo5Array {
            /*
            两个数组指向相同
         */
        public static void main(String[] args) {
            int[] arr1 = new int[2];
            arr1[0] = 11;
            arr1[1] = 22;
            /*
                数组类型的变量应该记录什么?
                    地址值
             */
            int[] arr2 = arr1;
            arr2[0] = 33;
            System.out.println(arr1[0]);
            System.out.println(arr1[1]);
            System.out.println("---------");
            System.out.println(arr2[0]);
            System.out.println(arr2[1]);
        }
    }
    

    注意:

    1.数组名称保存数组在堆内存空间的地址值

    2.使用数组名进行赋值时,传递的是地址值

    3.使用数组名作为方法参数和返回值,传递的都是地址值

    1.9 数组的静态初始化

    1.9.1 什么是静态初始化

    初始化时,就可以指定数组要存储的元素,系统还会自动计算出该数组的长度

    完整格式

    数据类型[] 数组名 = new 数据类型[]{元素1,元素2,...};

    范例:int [] arr=new int[]{1,2,3}; 

    简化格式

    数据类型[] 数组名 = {元素1,元素2,...};
    

      范例:int[]  arr={1,2,3}  

     public class Demo1Array {
            /*
                数组静态初始化 : 初始化时指定每个数组元素的初始值,由系统决定数组长度
    
                完整格式:
                            数据类型[] 数组名 = new 数据类型[]{数据1,数据2,数据3...};
                简化格式:
                            数据类型[] 数组名 = {数据1,数据2,数据3...};
             */
            public static void main(String[] args) {
                // 数据类型[] 数组名 = new 数据类型[]{数据1,数据2,数据3...};
                int[] arr = new int[]{11,22,33};
                System.out.println(arr[0]);
                System.out.println(arr[1]);
                System.out.println(arr[2]);
                // 数据类型[] 数组名 = {数据1,数据2,数据3...};
                int[] arr2 = {44,55,66};
                System.out.println(arr2);
                System.out.println(arr2[0]);
                System.out.println(arr2[1]);
                System.out.println(arr2[2]);
            }
    

    两种初始化的区别对比

    动态初始化:手动指定数组长度,由系统给出默认初始化值

    静态初始化:手动指定数组元素,系统会根据元素的个数,计算出数组的长度

    简化格式静态初始化不能分为两步完成。

    使用场景:

    动态初始化:只明确元素个数,不明确具体数值,推荐使用动态初始化

    例如:使用数组容器来存储键盘录入的5个整数

    int[] arr={?????}

    int [] arr=new int[5]

    静态初始化,需求中已经明确了要操作的具体数据,直接静态初始化即可

    例如:将一班的学生成绩存入数组11,22,33

    int [] arr={1,2,3};

    1.10 数组操作的两个常见问题

    1.10.1 索引越界异常

    • 出现原因

    • 访问了数组中不存在的索引,造成索引越界问题
    public class ArrayException {
        public static void main(String[] args) {
            int[] arr = new int[3]; // 0 1 2
            System.out.println(arr[2]);
    
            // 空指针异常
    
            arr = null; // 空值
            System.out.println(arr[0]);
        }
    }
    
    • 数组长度为3,索引范围是0~2,但是我们却访问了一个3的索引。

      程序运行后,将会抛出ArrayIndexOutOfBoundsException 数组越界异常。在开发中,数组的越界异常是不能出现的,一旦出现了,就必须要修改我们编写的代码。

    • 解决方案

      将错误的索引修改为正确的索引范围即可!

    1.10.2 空指针异常

    arr = null 这行代码,意味着变量arr将不会在保存数组的内存地址,也就不允许再操作数组了,因此运行的时候会抛出 NullPointerException 空指针异常。在开发中,空指针异常是不能出现的,一旦出现了,就必须要修改我们编写的代码。

    解决方案

    给数组一个真正的堆内存空间引用即可!

    数组常见操作

    1.11 数组遍历

    • 数组遍历:就是将数组中的每个元素分别获取出来,就是遍历。遍历也是数组操作中的基石。

    public class Test1Array {
        /*
            数组的遍历: 通过循环获取数组中的所有元素(数据)
    
            动态获取数组元素个数 : 数组名.length
         */
        public static void main(String[] args) {
            int[] arr = {11, 22, 33, 44, 55};
            // 数组名.length
            System.out.println("arr数组中元素的个数为:" + arr.length);
            //for(int i = 0; i < 5; i++){       手动写死了, 不严谨, 不推荐
            for(int i = 0; i < arr.length; i++){
                // i : 0 1 2 3 4
                System.out.println(arr[i]);
            }
        }
    }
    

    获取数组元素数量

    格式:数组名:length   

    范例:arr.length

    遍历通用格式:

     注意:遍历指的是取出数据的过程,不要局限理解为,遍历就是打印

    1.12 数组获取最大值

    • 最大值获取:从数组的所有元素中找出最大值

    • 实现思路:

      • 定义变量,保存数组0索引上的元素

      • 遍历数组,获取出数组中的每个元素

      • 将遍历到的元素和保存数组0索引上值的变量进行比较

      • 如果数组元素的值大于了变量的值,变量记录住新的值

      • 数组循环遍历结束,变量保存的就是数组中的最大值

    • 代码实现:

    public class Test2Array {
        /*
            实现步骤:
                    1. 假设数组中的第一个元素为最大值
                    2. 遍历数组, 获取每一个元素, 准备进行比较
                    3. 如果比较的过程中, 出现了比max更大的, 让max记录更大的值
                    4. 循环结束后, 打印最大值.
         */
        public static void main(String[] args) {
            int[] arr = {12,45,98,73,60};
            // 1. 假设数组中的第一个元素为最大值
            int max = arr[0];
            // 2. 遍历数组, 获取每一个元素, 准备进行比较
            for(int i = 1; i < arr.length; i++){
                // 3. 如果比较的过程中, 出现了比max更大的, 让max记录更大的值
                if(arr[i] > max){
                    max = arr[i];
                }
            }
            //  4. 循环结束后, 打印最大值.
            System.out.println("max:" + max);
        }
    }
    

    1.13 数组元素求和

    • 需求:键盘录入5个整数,存储到数组中,并对数组求和

    • 思路:

    • 1.创建键盘录入对象,准备键盘录入

    • 2.定义一个求和变量,准备记录累加后的结果

    • 3.动态初始化一个长度为5的int数组,准备存储键盘录入的数值

    • 4.将键盘录入的数值存储到数组中

    • 5.遍历数组,取出每一个元素,并求和

    • 6.输出总和

    import java.util.Scanner;
    public class Test3Array {
        /*
          思路:
              1.创建键盘录入对象,准备键盘录入
              2.定义一个求和变量,准备记录累加后的结果
              3.动态初始化一个长度为5的int数组,准备存储键盘录入的数值
              4.将键盘录入的数值存储到数组中
              5.遍历数组,取出每一个元素,并求和
              6.输出总和
       */
        public static void main(String[] args) {
            // 1.创建键盘录入对象,准备键盘录入
            Scanner sc = new Scanner(System.in);
            // 2.定义一个求和变量,准备记录累加后的结果
            int sum = 0;
            // 3.动态初始化一个长度为5的int数组,准备存储键盘录入的数值
            int[] arr = new int[5];
            // 4.将键盘录入的数值存储到数组中
            for(int i = 0; i < arr.length; i++){
                System.out.println("请输入第" + (i+1) + "个整数:");
                //arr[i] = 10;
                arr[i] = sc.nextInt();
            }
    
            // 5.遍历数组,取出每一个元素,并求和
            for (int i = 0; i < arr.length; i++) {
                sum += arr[i];
            }
    
            // 6.输出总和
            System.out.println("sum:" + sum);
    
        }
    }
    

    1.14 数组基本查找【应用】

    - 需求:
    已知一个数组 arr = {19, 28, 37, 46, 50}; 键盘录入一个数据,查找该数据在数组中的索引,并在控
    制台输出找到的索引值。

    分析:

    键盘录入一个数据后,让这个数据和数据中的每一个元素进行比较,如果数据值相等,返回该数据值对应的索引即可

    但是,假如录入了一个数组中不存在的数据,这个时候,就没有任何内容输出了,很明显是有问题的,在实际的开发中,如果对应的索引不存在,我们一般都是返回一个负数,而且经常用-1来表示。

    思路:

    1.定义一个数组,用静态初始化完成数组元素的初始化

    2.键盘录入要查找的数据,用一个变量接收

    3.定义一个索引变量,初始值为-1

    4.遍历数组,获取到数组中的每一个元素

    5.拿键盘录入的数据和数组中的每一个元素进行比较,如果值相同,就把该值对应的索引赋值给索引变量,并结束循环

    6.输出索引变量

    import java.util.Scanner;
    
    public class Test4Array {
        /*
           思路:
                1.定义一个数组,用静态初始化完成数组元素的初始化
                2.键盘录入要查找的数据,用一个变量接收
                3.定义一个索引变量,初始值为-1
                4.遍历数组,获取到数组中的每一个元素
                5.拿键盘录入的数据和数组中的每一个元素进行比较,如果值相同,就把该值对应的索引赋值给索引变量,并结束循环
                6.输出索引变量
         */
        public static void main(String[] args) {
            // 1.定义一个数组,用静态初始化完成数组元素的初始化
            int[] arr = {19, 28, 37, 46, 50};
            // 2.键盘录入要查找的数据,用一个变量接收
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入您要查找的元素:");
            int num = sc.nextInt();
            // 3.定义一个索引变量,初始值为-1
            // 假设要查找的数据, 在数组中就是不存在的
            int index = -1;
            // 4.遍历数组,获取到数组中的每一个元素
            for (int i = 0; i < arr.length; i++) {
                // 5.拿键盘录入的数据和数组中的每一个元素进行比较,如果值相同,就把该值对应的索引赋值给索引变量,并结束循环
                if (num == arr[i]) {
                    // 如果值相同,就把该值对应的索引赋值给索引变量,并结束循环
                    index = i;
                    break;
                }
            }
            //  6.输出索引变量
            System.out.println(index);
        }
    }
    

    1.15 评委打分【应用】

    • 需求:在编程竞赛中,有6个评委为参赛的选手打分,分数为0-100的整数分。 选手的最后得分为:去掉一个最高分和一个最低分后 的4个评委平均值 (不考虑小数部分)。 

    思路:
    1.定义一个数组,用动态初始化完成数组元素的初始化,长度为6
    2.键盘录入评委分数
    3.由于是6个评委打分,所以,接收评委分数的操作,用循环
    4.求出数组最大值
    5.求出数组最小值
    6.求出数组总和
    7.按照计算规则进行计算得到平均分
    8.输出平均分

    import java.util.Scanner;
    
    public class Test5Array {
        /*
            思路:
                1.定义一个数组,用动态初始化完成数组元素的初始化,长度为6
                2.键盘录入评委分数
                3.由于是6个评委打分,所以,接收评委分数的操作,用循环
                4.求出数组最大值
                5.求出数组最小值
                6.求出数组总和
                7.按照计算规则进行计算得到平均分
                8.输出平均分
         */
        public static void main(String[] args) {
            // 1.定义一个数组,用动态初始化完成数组元素的初始化,长度为6
            int[] arr = new int[6];
            // 2.键盘录入评委分数
            Scanner sc = new Scanner(System.in);
            //  3.由于是6个评委打分,所以,接收评委分数的操作,用循环
            for (int i = 0; i < arr.length; i++) {
                System.out.println("请输入第" + (i+1) + "个评委的打分:");
                int score = sc.nextInt();
                if(score >= 0 && score <= 100){
                    // 合法的分值
                    arr[i] = score;
                }else{
                    // 非法的分值
                    System.out.println("您的打分输入有误, 请检查是否是0-100之间的");
                    i--;
                }
            }
    
            // 4.求出数组最大值
            int max = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if(max < arr[i]){
                    max = arr[i];
                }
            }
    
            // 5.求出数组最小值
            int min = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if(min > arr[i]){
                    min = arr[i];
                }
            }
    
            // 6.求出数组总和
            int sum = 0;
            for (int i = 0; i < arr.length; i++) {
                sum += arr[i];
            }
    
            // 7.按照计算规则进行计算得到平均分
            int avg = (sum - max - min ) / 4;
    
            // 8.输出平均分
            System.out.println(avg);
        }
    }
    

      

      

      

     

      

      

      

      

      

  • 相关阅读:
    Linux 清空nohup.out(引用别人的文章)
    Nginx map模块
    Nginx 防盗链 secure_link 模块
    Nginx HTTP框架提供的其它变量
    NC 命令引用了一个高手的文章做收藏
    Nginx HTTP框架提供的请求相关变量
    6 MyISAM和InnoDB
    5.MVCC
    4 乐观锁和悲观锁
    Redis原理
  • 原文地址:https://www.cnblogs.com/faded8679/p/13849655.html
Copyright © 2020-2023  润新知