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);
    }
}

  

  

  

 

  

  

  

  

  

 

posted @ 2020-10-20 22:48  星梦泪痕  阅读(126)  评论(0)    收藏  举报