JavaEE基础第三章数组

数组

数组的概述

  1. 数组的理解:数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理

  2. 数组的相关概念

    • 数组名
    • 元素
    • 角标、下标、索引
    • 数组的长度:元素的个数
  3. 数组的特点:

    • 数组是有序排列的

    • 数组属于引用数据类型。数组的元素既可以是基本数据类型,也可以是引用数据类型(如String)

    • 创建数组对象会在内存中开辟一整块连续的内存空间

    • 数组的长度一旦确定,就不能修改。

  4. 数组的分类:

    • 按照维数:一维数组、二维数组、…
    • 按照数组元素的类型:基本数据类型元素的数组、引用数据类型元素的数组
  5. 一维数组的使用

    ①一维数组的声明和初始化

    ②如何调用数组的指定位置的元素

    ③如何获取数组的长度

    ④如何遍历数组

    ⑤数组元素的默认初始化

    ⑥数组的内存解析

//1.一维数组的声明和初始化

int[] ids;//声明
//1.1静态初始化:数组的初始化和数组元素的赋值操作同时进行
ids = new int[]{1001,1002,1003,1004};
//1.2动态初始化:数组的初始化和数组元素的赋值操作分开进行
String[] names = new String[5];//只需声明数组的长度即可,切不可同时声明元素
//总结:数组一旦初始化完成,其长度就确定了
//2.如何调用数组的指定位置的元素:通过下标的方式调用
//数组下标从0开始,到数组长度-1结束。
names[0] = "赵";
names[1] = "钱";
names[2] = "孙";
names[3] = "李";
names[4] = "刘";
//3.如何获取数组的长度
//属性:length
System.out.println(names.length);//5
//4.遍历数组(利用循环)
for(int i = 0;i < names.length;i++){
    System.out.println(names[i]);
}
//5.数组元素的默认初始化值
/*
基本数据类型时
>数组元素是整型:0
>数组元素是浮点型:0.0
>数组元素是char型:0或'\u0000',而非'0'
>数组元素是bool型:false

引用数据类型时:null
*/

内存的简化结构

JavaEE基础第三章数组

以后只要见到new一个对象,那么堆空间中就重新开辟

一维数组内存解析图解

JavaEE基础第三章数组

真实的字符串等引用数据类型并不是放在数组中的,而是放在方法区中的常量池,数组中存放的是指向它的指针,现在不用了解太多,后续面向对象还会讲。(引用数据类型要么存放地址值,要么就是null)

一维数组练习题

public class Project {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入学生的人数");

        int stuNum = scanner.nextInt();
        int[] scores = new int[stuNum];
        System.out.println("请输入学生的成绩");
        int max = 0;
        for (int i = 0; i < scores.length; i++) {
            int grades = scanner.nextInt();
            scores[i] = grades;
            //找出最大成绩

            if (max < scores[i]){
                max = scores[i];
            }
        }
        System.out.println("最高分是" + max);
        for (int i = 0; i < scores.length; i++) {
            if(max - scores[i] <= 10){
                System.out.println("student " + i +" score is " + scores[i] + " grade is " + 'A');
            }else if (max - scores[i] <= 20){
                System.out.println("student " + i +" score is " + scores[i] + " grade is " + 'B');
            }else if (max - scores[i] <= 30){
                System.out.println("student " + i +" score is " + scores[i] + " grade is " + 'C');
            }else {
                System.out.println("student " + i +" score is " + scores[i] + " grade is " + 'D');
            }
        }
    }
}

二维数组的使用

  1. 理解:可以把二维数组看成是一维数组array1又作为另一个一维数组array2的元素而存在。其实,从数组底层的运行机制来看,并没有多维数组。

  2. 二维数组的使用

    ①二维数组的声明和初始化

    ②如何调用数组的指定位置的元素

    ③如何获取数组的长度

    ④如何遍历数组

    ⑤数组元素的默认初始化

    ⑥数组的内存解析

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

        int[] arr1 = new int[]{1, 2, 3};
        //如下方式也是正确的,不标准
        int arr7[] = new int[]{1,2,3};
        //省略也正确,不标准
        int[] arr8 = {1,2,3};//类型推断

        //1.二维数组的声明和初始化
        //静态初始化
        int[][] arr2 = new int[][]{{1,2,3},{4,5},{6,7,8}};
        //动态初始化1
        int[][] arr3 = new int[3][2];
        //动态初始化2
        int[][] arr4 = new int[3][];
        //如下定义也正确,不常用,不标准
        int arr5[][] = new int[3][];
        int[] arr6[] = new int[3][];
        //省略也正确,不标准
        int[][] arr9 = {{1,2,3},{4,5},{6,7,8}};//类型推断

        //2.如何调用数组指定位置的元素
        System.out.println(arr2[0][1]);//2
        System.out.println(arr3[1][1]);//0

        //arr4还没有初始化完,若直接调指定位置元素会报错,所以要先初始化完
        //从二维数组的结构去理解,一个数组去充当另一个数组的元素
        arr4[1] = new int[4];
        System.out.println(arr4[1][2]);//0

        //3.获取二维数组的长度
        System.out.println(arr2.length);//3
        System.out.println(arr2[0].length);//3
        System.out.println(arr2[1].length);//2

        //4.遍历二维数组,用到两层for循环
        for (int i = 0; i < arr2.length; i++) {
            for (int j = 0; j < arr2[i].length; j++) {
                System.out.print(arr2[i][j] + "    ");
            }
            System.out.println();

        }

        //5.数组元素的默认初始化值
        /*
        规定:二维数组分为外层数组元素,内层数组元素
        int[][] arr = new int[4][3];
        外层元素:arr[0],arr[1]等
        内层元素:arr[0][0],arr[1][2]等
         */
        System.out.println(arr3[0]);//[I@1b6d3586,是一个内存地址,I代表int类型
        System.out.println(arr3[0][0]);//0
        System.out.println(arr3);//[[I@4554617c,同样也是一个地址值

        String[][] arr10 = new String[4][3];
        System.out.println(arr10[1]);//地址值
        System.out.println(arr10[1][1]);//null

        double[][] arr11 = new double[4][];
        System.out.println(arr11[1]);//null,因为二维数组可以看成一个一维数组放到另一个一维数组中,数组是引用数据类型,默认值都是null
        System.out.println(arr11[1][1]);//报错,会报空指针异常,因为指向下一个数组的指针不存在
    }
}

图解

JavaEE基础第三章数组

JavaEE基础第三章数组

arr是一个地址值

二维数组的内存解析

JavaEE基础第三章数组

数组中设计的常见算法

  1. 数组元素的赋值(杨辉三角、回形数等)
  2. 求数值型数组中元素的最大值、最小值、平均数、总和等
  3. 数组的复制、反转、查找(线性查找、二分查找)
  4. 数组元素的排序算法

其中1,4在面试中考察的比较多一些

以下操作是赋值,不是数组的复制

    public static void main(String[] args) {
        int[] array1,array2;
        array1 = new int[]{2,3,5,7,11,13,17,19};
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "  ");
        }
        //赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[2] = 2),打印出array1
        array2 = array1;//这个操作只是将array1的地址值给了array2
        for (int i = 0; i < array2.length; i++) {
            if (i % 2 == 0){
                array2[i] = i;
            }
        }
        System.out.println();
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "  ");
        }
    }

图解如上代码,只要是new一个,就会在堆中新开辟一个空间,此段代码只new了一个,因此堆中只有一个

JavaEE基础第三章数组

真正的复制

//将array1的值复制给array2
        array2 = new int[array1.length];
        for (int i = 0; i < array1.length; i++) {
            array2[i] = array1[i];
        }

图解复制,中间new了两个

JavaEE基础第三章数组

数组的反转,以后进行反转操作都可以用以下两种方法

    public static void main(String[] args) {
        String[] arr = new String[]{"赵","钱","孙","李"};
        //数组的反转
        //方式一
        for (int i = 0; i < arr.length / 2; i++) {
            String temp = arr[i];
            arr[i] = arr[arr.length - i - 1];
            arr[arr.length - i - 1] = temp;
        }
        //方式二
        for (int i = 0,j = arr.length - 1; i < j; i++,j--) {
            String temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
        //遍历
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

查找(线性查找)

        String[] arr = new String[]{"赵","钱","孙","李"};

        //查找(线性查找,从前往后查)
        String dest = "孙";
        dest = "刘";
        //设置标志
        boolean flag = true;
        for (int i = 0; i < arr.length; i++) {
            if (dest.equals(arr[i])){
                System.out.println("找到了" + dest + "的位置在" + i);
                flag = false;
                break;
            }

        }
        if (flag){
            System.out.println("很抱歉没有找到!");
        }
		/*
		或者改为
		if(i == arr.length){
			System.out.println("很抱歉没有找到!");
		}
		循环到i = arr.length - 1;i++,此时i = arr.length,不满足循环条件,则跳出循环
		*/

二分查找(前提是数组有序),先熟悉,开发中有专门方法

//二分法查找
        int[] arr = new int[]{-10,-6,0,2,5,8};
        Scanner scanner = new Scanner(System.in);
        while (true){
            System.out.println("请输入要查找的数字");
            int num = scanner.nextInt();
            if (num == -1){
                System.out.println("程序运行结束!");
                break;
            }
            int head = 0;//初始化头部索引
            int end = arr.length - 1;//初始化尾部索引
            //定义标志位
            boolean flag = true;

            while (head <= end){
                int mid = (head + end) / 2;
                if (num == arr[mid]){
                    System.out.println("找到了指定元素位置" + mid);
                    flag = false;
                    break;
                }else if (arr[mid] < num){
                    head = mid + 1;
                }else {
                    end = mid - 1;
                }
            }
            if (flag){
                System.out.println("抱歉没有找到");
            }
        }

排序

  • 选择排序:每一趟在待排序元素中选取关键字最小(或最大)的元素加入有序子序列

  • 插入排序:基本思想:每次将一个待排序的元素,按其关键字的大小插入到前面已经排好序的子文件的适当位置,直到全部记录插入完成为止。

  • 冒泡排序(属于交换排序,每次比较相邻元素)

//冒泡排序(升序)
        int[] arr = new int[]{-1,-3,-9,0,9,3,8};
        //轮数,需要length - 1 轮
        for (int i = 0; i < arr.length - 1; i++) {
            //比较相邻元素的值,且每次都要少比较一个
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]){
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;

                }
            }
            
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }

快速排序(使用最多效果最好的),目前知道过程即可

	private static void swap(int[] data, int i, int j) {
		int temp = data[i];
		data[i] = data[j];
		data[j] = temp;
	}

	private static void subSort(int[] data, int start, int end) {
		if (start < end) {
			int base = data[start];
			int low = start;
			int high = end + 1;
			while (true) {
				while (low < end && data[++low] - base <= 0)
					;
				while (high > start && data[--high] - base >= 0)
					;
				if (low < high) {
					swap(data, low, high);
				} else {
					break;
				}
			}
			swap(data, start, high);
			
			subSort(data, start, high - 1);//递归调用
			subSort(data, high + 1, end);
		}
	}
	public static void quickSort(int[] data){
		subSort(data,0,data.length-1);
	}
	
	
	public static void main(String[] args) {
		int[] data = { 9, -16, 30, 23, -30, -49, 25, 21, 30 };
		System.out.println("排序之前:\n" + java.util.Arrays.toString(data));
		quickSort(data);
		System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
	}

快速排序图解

JavaEE基础第三章数组

算法性能对比:背下冒泡平均复杂度O(n2),快速排序平均时间复杂的O(nlogn)

JavaEE基础第三章数组

Arrays工具类

java中封装了很多工具类可以加快开发速度,需要用到的时候直接调用即可(不知道的可以查看API文档)

    public static void main(String[] args) {
        //判断两个数组是否相等
        int[] arr1 = new int[]{1,2,3,4};
        int[] arr2 = new int[]{1,3,2,4};
        boolean isEquals = Arrays.equals(arr1,arr2);
        System.out.println(isEquals);
        //输出数组信息
        System.out.println(Arrays.toString(arr1));
        //将指定值填充到数组中
        Arrays.fill(arr2,10);
        System.out.println(Arrays.toString(arr2));//[10,10,10,10]
        //对数组进行排序
        int[] arr3 = new int[]{-10,-3,3,42,2};
        Arrays.sort(arr3);
        System.out.println(Arrays.toString(arr3));
        //对排序后的数组进行二分查找
        int index = Arrays.binarySearch(arr3,3);
        System.out.println(index);
    }

数组中常见异常:

  • 数组角标越界的异常:ArrayIndexOutOfBoundsExcetion

上下界都不能超过

  • 空指针异常:NullPointerException
        //情况一:
        int[] arr5 = new int[]{1,2,3};
        arr5 = null;
        System.out.println(arr5[0]);
        //情况二
        int[][] arr6 = new int[4][];
        System.out.println(arr6[0][0]);
        //情况三
        String[] arr7 = new String[]{"a","b","c"};
        arr7[0] = null;
        System.out.println(arr7[0].toString());
上一篇:解决@Table(name = “t_user“)出现“Cannot resolve table ‘t_user‘“问题


下一篇:JavaEE基础 第八节 异常