Java SE 学习笔记(三)—— 数组

目录

  • 1 一维数组
    • 1.1 数组的定义
    • 1.2 数组的初始化
      • 1.2.1 静态初始化
      • 1.2.2 动态初始化
    • 1.3 数组的访问
    • 1.4 内存分配
      • 1.4.1 内存分配给一个数组
      • 1.4.2 内存分配给两个数组
      • 1.4.3 多个数组指向相同内存图
    • 1.5 数组的操作
      • 1.5.1 数组的遍历
      • 1.5.2 数组元素求和
      • 1.5.3 数组获取最值
      • 1.5.5 数组反转
      • 1.5.6 数组的基本查找
      • 1.5.7 数组综合案例
  • 2 二维数组
    • 2.1 数组的定义
    • 2.2 数组的初始化
    • 2.3 数组的操作
  • 3 Arrays类

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

1 一维数组

1.1 数组的定义

容器:是将多个数据存储到一起,每个数据称为该容器的元素
数组:数组就是存储数据 长度固定 的容器,保证多个数据的数据类型要一致

第一种格式(推荐):

数据类型[] 数组名;
int[] arr;        
double[] arr;      
char[] arr;

第二种格式:

数据类型 数组名[];
int arr[];
double arr[];
char arr[];

1.2 数组的初始化

1.2.1 静态初始化

在创建数组时,直接将元素确定 ,系统还会自动计算出该数组的长度

完整版格式

数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3...};
int[] arr = new int[]{1,2,3,4,5};

简化版格式

数据类型[] 数组名 = {元素1,元素2,元素3...};
int[] arr = {1,2,3,4,5};

❗️ 注意:

  • 数组有 定长 特性,长度一旦指定,不可更改
  • 什么类型的数组存放什么类型的数据,否则报错

1.2.2 动态初始化

数组动态初始化就是只给定数组的类型和长度,由系统给出默认初始化值,之后再存入具体数据

数据类型[] 数组名 = new 数据类型[数组长度];
int[] arr = new int[3];// 系统默认给出数组元素的初始值为0
System.out.println(arr); // [I@1b6d3586

❗️注意:

  • 数组变量名中存储的是数组在内存中的地址,打印数组变量名时会输出数组的内存地址
  • 例如:[I@10f87f48
    • @ : 分隔符
    • [ : 当前的空间是一个数组类型
    • I : 当前数组容器中所存储的数据类型
    • 10f87f48 : 十六进制内存地址

在初始化的时候,手动指定数组的长度,系统会为数组容器分配默认初始值:

Java SE 学习笔记(三)—— 数组_第1张图片

❗️注意:

  • 引用数据类型:引用、记录了地址值的变量,其所对应的数据类型就是引用数据类型。例如int[] arr = new int[3];
  • null,空值,引用数据类型的默认值,表示不指向任何有效对象。当arr=null;打印该数组名称会出现空指针异常。

1.3 数组的访问

索引: 每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引 (index),可以通过数组的索引访问到数组中的元素。

数组名[索引]

数组的长度属性: 每个数组都具有长度,而且是固定的,Java中赋予了数组的一个属性,可以获取到数组的长度,

数组名.length

属性length的执行结果是数组的长度,int类型结果。由次可以推断出,数组的最大索引值为 数组名.length-1

1.4 内存分配

内存是计算机中的重要原件,临时存储区域,作用是运行程序。
​我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存。

​Java虚拟机要运行程序,必须要对内存进行空间的分配和管理。

Java中的内存分配

Java SE 学习笔记(三)—— 数组_第2张图片

1.4.1 内存分配给一个数组


Java SE 学习笔记(三)—— 数组_第3张图片

1.4.2 内存分配给两个数组


Java SE 学习笔记(三)—— 数组_第4张图片

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


Java SE 学习笔记(三)—— 数组_第5张图片

❗️注意:

  • new一次就会在堆中开辟出一片新的空间,堆内存的空间地址不会出现重复的现象。
  • 如果数组变量中没有存储数组的地址,而是null,如令arr=null;在访问数组信息的时候会报空指针异常

1.5 数组的操作

1.5.1 数组的遍历

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

public static void main(String[] args) {
    int[] arr = {1, 2, 3, 4, 5};
    for (int i = 0; i < arr.length; i++) {
        System.out.println(arr[i]);
    }
}

1.5.2 数组元素求和

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

import java.util.Scanner;

public class Test{
    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.5.3 数组获取最值

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

✨ 实现思路:

  • 定义变量,保存数组0索引上的元素
  • 遍历数组,获取出数组中的每个元素
  • 将遍历到的元素和保存数组0索引上值的变量进行比较
  • 如果数组元素的值大于了变量的值,变量记录住新的值
  • 数组循环遍历结束,变量保存的就是数组中的最大值
public static void main(String[] args) {
    int[] arr = {5, 15, 2000, 10000, 100, 4000};
    //定义变量,保存数组中0索引的元素
    int max = arr[0];
    // 遍历数组,取出每个元素
    for (int i = 1; i < arr.length; i++) {
        //遍历到的元素和变量max比较
        // 如果数组元素大于max
        if (arr[i] > max) {
            //max记录住大值
            max = arr[i];
        }
    }
    System.out.println("数组最大值是: " + max);
}

1.5.5 数组反转

数组的反转: 数组中的元素颠倒顺序,例如原始数组为1,2,3,4,5,反转后的数组为5,4,3,2,1

实现思想:数组最远端的元素互换位置。

  • 实现反转,就需要将数组最远端元素位置交换
  • 定义两个变量,保存数组的最小索引和最大索引
  • 两个索引上的元素交换位置
  • 最小索引++,最大索引–,再次交换位置
  • 最小索引超过了最大索引,数组反转操作结束
public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        /*循环中定义变量min=0最小索引 max=arr.length‐1最大索引 min++,max‐‐ */
        for (int min = 0, max = arr.length-1; min < max; min++, max--) {
            int temp = arr[min];
            arr[min] = arr[max];
            arr[max] = temp;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }

1.5.6 数组的基本查找

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

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.5.7 数组综合案例

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

import java.util.Scanner;

public class Test {
    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--; // 如果输入错误的数据,则会赋默认值0,接着输入下一个值,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);
    }
}

进一步的数据相关操作:

  • 数组排序技术
    • 冒泡排序
    • 选择排序
    • 快速排序
    • 插入排序
    • ……
  • 数组搜索技术
    • 二分查找
    • 分块查找
    • 哈希表查找
    • ……
      可参考 Java SE 学习笔记(十二)—— 数据结构与算法

2 二维数组

2.1 数组的定义

二维数组也是一种容器,不同于一维数组,该容器存储的都是一维数组容器

第一种格式(推荐):

数据类型[][] 变量名;
int[][] arr;

第二种格式:

数据类型 变量名[][];
int arr[][];

第三种格式:

数据类型[] 变量名[];
int[] arr[];

2.2 数组的初始化

  1. 动态初始化
数据类型[][] 变量名 = new 数据类型[m][n];
// m表示这个二维数据可以存放多少个一维数组
// n表示每一个一维数组可以存放多少个元素

int[][] arr = new int[2][3];

注意: 二维数组中存储的是一维数组的 内存地址

问:二维数组中存储的是一维数组, 那能不能存入 【提前创建好的一维数组】呢 ?
答 : 可以的

public static void main(String[] args) {
    int[] arr1 = {11,22,33};
    int[] arr2 = {44,55,66};
    int[] arr3 = {77,88,99,100};

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

    // arr[2][3] = 100; 索引越界,会报错!

    arr[0] = arr1;
    arr[1] = arr2;
    arr[2] = arr3;

    System.out.println(arr[1][2]); // 66
    System.out.println(arr[2][3]); // 100 索引好像是“越界”,但不会报错!
}

问:为什么提前创建好一维数组去访问不会报错,而直接访问数组存入数据却会报错?

Java SE 学习笔记(三)—— 数组_第6张图片

这种动态初始化在创建时就会把这三个一维数组创建好,并且里面的索引也是固定的,用 arr[0][3] 去访问一个不存在的索引必然会报错。

Java SE 学习笔记(三)—— 数组_第7张图片

提前创建一维数组再往里面赋值的方式,只是做了 内存地址的替换,跟原来一维数组的长度已经没有关系了。

  1. 静态初始化

完整格式

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

简化格式

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

2.3 数组的操作

(1)数组的遍历

public static void main(String[] args) {
    int[][] arr = {{11, 22, 33}, {33, 44, 55}};

    // 1. 遍历二维数组,取出里面每一个一维数组
    for (int i = 0; i < arr.length; i++) {
        //System.out.println(arr[i]);
        // 2. 在遍历的过程中,对每一个一维数组继续完成遍历,获取内部存储的每一个元素
        //int[] temp = arr[i];
        for (int j = 0; j < arr[i].length; j++) {
            System.out.println(arr[i][j]);
        }
    }
}

(2)数组元素求和

public static void main(String[] args) {
    // 1. 定义求和变量,准备记录最终累加结果
    int sum = 0;
    // 2. 使用二维数组来存储数据,再将4个一维数组装起来
    int[][] arr = { {22,66,44} , {77,33,88} , {25,45,65} , {11,66,99}};
    // 3. 遍历二维数组,获取所有元素,累加求和
    for (int i = 0; i < arr.length; i++) {
        for(int j = 0; j < arr[i].length; j++){
            sum += arr[i][j];
        }
    }
    // 4. 输出最终结果
    System.out.println(sum); // 641
}

3 Arrays类


Arrays类是操作数组的工具类,包含用来操作数组的各种方法,比如排序和搜索等。其所有方法均为静态方法,调用起来非常简单。

常用方法如下:

Java SE 学习笔记(三)—— 数组_第8张图片

举个栗子:

public static void main(String[] args) {
    int[] intArray = {10, 20, 30};
    // 将int[]数组按照默认格式变成字符串
    String intStr = Arrays.toString(intArray);
    System.out.println(intStr); // [10, 20, 30]
	
	// 排序
    int[] array1 = {2, 1, 3, 10, 6};
    Arrays.sort(array1); // 底层使用快速排序算法
    System.out.println(array1); // [I@1b6d3586
    System.out.println(Arrays.toString(array1)); // [1, 2, 3, 6, 10]

    String[] array2 = {"bbb", "aaa", "ccc"};
    Arrays.sort(array2);
    System.out.println(array2); // [Ljava.lang.String;@4554617c
    System.out.println(Arrays.toString(array2)); // [aaa, bbb, ccc]
	
	// 二分搜索
	int [] arr = {1,2,3,4,5,6,7,8,9,10};
	int index = Arrays.binarySearch(arr, 0);
	System.out.println(index);
	//1,数组必须有序
	//2.如果要查找的元素存在,那么返回的是这个元素实际的索引
	//3.如果要查找的元素不存在,那么返回的是 (-插入点索引-1)
		//插入点索引:如果这个元素在数组中,他应该在哪个索引上.

❗️ 注意:

  • 如果是数值,sort 默认按照升序从小到大
  • 如果是字符串,sort 默认按照字母升序

案例:倒序打印字符串

请使用 Arrays 相关的API,将一个随机字符串中的所有字符升序排列,并倒序打印。

public static void main(String[] args) {
	String str = "asv76agfjh";

	// 如何进行升序排列:sort
	// 必须是一个数组,才能用Arrays.sort方法
	// String --> 数组,用toCharArray
	char[] chars = str.toCharArray();
	Arrays.sort(chars); // 对字符数组进行升序排列

	// 需要倒序遍历
	for (int i = chars.length - 1; i >= 0; i--) {
		System.out.print(chars[i]+" "); // v s j h g f a a 7 6
	}
}

Arrays 类对于 Comparator 比较器的支持

Java SE 学习笔记(三)—— 数组_第9张图片

自定义排序规则

  • 设置 Comparator 接口对应的比较器对象,来定制比较规则
    • 如果认为左边的数据大于右边的数据,返回正整数
    • 如果认为左边的数据小于右边的数据,返回负整数
    • 如果认为左边的数据等于右边的数据,返回 0

举个栗子:

import java.util.Arrays;
import java.util.Comparator;

public class Demo {
    public static void main(String[] args) {

//        Arrays的sort方法对于有值特性的数组默认是升序排序
        int [] arr = {9,2,31,4,5,16,7,10};
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr)); // [2, 4, 5, 7, 9, 10, 16, 31]

        // 现在需要对arr降序排序(自定义比较器对象,只能支持应用类型的排序)
        Integer[] arr1= {9,2,31,4,5,16,7,10};
        Arrays.sort(arr1, new Comparator<Integer>() {
            /**
             * 参数一:被排序的数组,必须是引用类型的元素
             * 参数二:匿名内部类对象,代表了一个比较器对象
             */
            @Override
            public int compare(Integer o1, Integer o2) {
                // 制定比较规则(默认升序)
                // 方式1
//                if(o1>o2){
//                    return 1;
//                } else if (o1
//                    return -1;
//                }
//                return 0;
                // 方式2
//                return o1-o2;

                // 改成降序
                return o2-o1;
            }
        });
        System.out.println(Arrays.toString(arr1)); // [31, 16, 10, 9, 7, 5, 4, 2]
    }
}

对于自定义对象的排序

Student类

public class Student {
    private String name;
    private int age;
    private double height;

    public Student() {
    }

    public Student(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
}

Demo类

import java.util.Arrays;
import java.util.Comparator;

public class Demo {
    public static void main(String[] args) {

        Student s1 = new Student("张三", 26, 173.2);
        Student s2 = new Student("李四", 19, 163.9);
        Student s3 = new Student("王五", 23, 183.9);
        Student[] ss = new Student[3];
        ss[0] = s1;
        ss[1] = s2;
        ss[2] = s3;
        System.out.println(Arrays.toString(ss));  // 记得重写Student类中的toString方法

//        Arrays.sort(ss); // 直接报错,Java不知道按照什么规则排序

        Arrays.sort(ss, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                // 整型比较
//                return o1.getAge()-o2.getAge(); // 按照年龄升序排序
//                return o2.getAge()-o1.getAge(); // 按照年龄降序排序
                // 浮点型比较
//                return Double.compare(o1.getHeight(),o2.getHeight());// 按照身高升序排序
                return Double.compare(o2.getHeight(),o1.getHeight());// 按照身高降序排序
            }
        });
        System.out.println(Arrays.toString(ss));
    }
}

你可能感兴趣的:(Java,java,学习)