Java数组的概述(第5章)

一维数组


1. 数组的理解(Array)

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

简称:多个数据的组合

Java中的容器:数组、集合框架(第12章):在内存中对多个数据的存储。

2. 几个相关的概念


> 数组名
> 数组的元素(即内部存储的多个元素)
> 数组的下标、角标、下角标、索引、index(即找到指定数组元素所使用的编号)
> 数组的长度(即数组容器中存储的元素的个数)

3. 数组的特点


> 数组中的元素在内存中是依次紧密排列的,有序的。
> 数组,属于引用数据类型的变量。数组的元素,既可以是基本数据类型,也可以引用数据类型。
> 数组,一旦初始化完成,其长度就确定了,并且其长度不可更改。
> 创建数组对象会在内存中开辟一整块`连续的空间`。占据的空间的大小,取决于数组的长度和数组中元素的类型。

4. 复习:变量按照数据类型的分类


4.1 基本数据类型:byte \ short \ int \ long ;float \ double ; char \ boolean
4.2 引用数据类型:类、数组、接口、枚举、注解、记录

5. 数组的分类


5.1 按照元素的类型: 基本数据类型元素的数组;引用数据类型元素的数组
5.2 按照数组的维数来分:一维数组;二维数组;.....

 

6. 一维数组的使用(6个基本点)

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

> 数组的声明和初始化

//复习:变量的定义格式:数据类型 变量名 = 变量值
		int num1 = 10;
		int num2; //声明
		num2 = 20; //初始化

		//1.1 声明数组
		double[] prices;
		//1.2 数组的初始化
		//静态初始化:数组变量的赋值与数组元素的赋值操作同时进行。
		prices = new double[]{20.32,43.21,43.22};

//		String[] foods;
//		foods = new String[]{"拌海蜇","龙须菜","炝冬笋","玉兰片"};

		//数组的声明和初始化
		//动态初始化:数组变量的赋值与数组元素的赋值操作分开进行。
		String[] foods = new String[4];

		//其它正确的方式
		int arr[] = new int[4];
		int[] arr1 = {1,2,3,4}; //类型推断

		//错误的方式
//		int[] arr2 = new int[3]{1,2,3};
//		int[3] arr3 = new int[];

> 调用数组的指定元素

//通过角标的方式,获取数组的元素
		//角标的范围从0开始,到数组的长度-1结束
		System.out.println(prices[0]);
		System.out.println(prices[2]);
//		System.out.println(prices[4]); //报异常:ArrayIndexOutOfBoundsException

		foods[0] = "拌海蜇";
		foods[1] = "龙须菜";
		foods[2] = "炝冬笋";
		foods[3] = "玉兰片";
//		foods[4] = "酱茄子"; //报异常:ArrayIndexOutOfBoundsException

> 数组的属性:length,表示数组的长度

//使用length属性表示
		System.out.println(foods.length);//4
		System.out.println(prices.length);//3

> 数组的遍历

//	    System.out.println(foods[0]);
//		System.out.println(foods[1]);
//		System.out.println(foods[2]);
//		System.out.println(foods[3]);

		for(int i = 0;i < foods.length;i++){
			System.out.println(foods[i]);
		}

		for (int i = 0; i < prices.length; i++) {
			System.out.println(prices[i]);
		}

	


> 数组元素的默认初始化值

//> 整型数组元素的默认初始化值:0
        int[] arr1 = new int[3];
        System.out.println(arr1[0]);

        short[] arr2 = new short[4];
        for (int i = 0; i < arr2.length; i++) {
            System.out.println(arr2[i]);
        }

        //> 浮点型数组元素的默认初始化值:0.0
        double[] arr3 = new double[5];
        System.out.println(arr3[0]);


        //> 字符型数组元素的默认初始化值:0 (或理解为'\u0000')
        char[] arr4 = new char[4];
        System.out.println(arr4[0]);

        if(arr4[0] == 0){
            System.out.println("1111");
        }

        if(arr4[0] == '0'){
            System.out.println("2222");
        }

        if(arr4[0] == '\u0000'){
            System.out.println("3333");
        }

        System.out.println(arr4[0] + 1);

        //> boolean型数组元素的默认初始化值:false
        boolean[] arr5 = new boolean[4];
        System.out.println(arr5[0]);

        //> 引用数据类型数组元素的默认初始化值:null
        String[] arr6 = new String[5];
        for (int i = 0; i < arr6.length; i++) {
            System.out.println(arr6[i]);
        }

        if(arr6[0] == null){
            System.out.println("aaaa");
        }

        if(arr6[0] == "null"){
            System.out.println("bbbb");
        }

> 一维数组的内存解析(难)

        int[] a1 = new int[]{1,2,3};
        int[] a2 = a1;
        a2[1] = 10;
        System.out.println(a1[1]);
        System.out.println(a1);
        System.out.println(a2);


    }
}

7. 数组元素的默认初始化值的情况


注意:以数组的动态初始化方式为例说明。

> 整型数组元素的默认初始化值:0
> 浮点型数组元素的默认初始化值:0.0
> 字符型数组元素的默认初始化值:0 (或理解为'\u0000')
> boolean型数组元素的默认初始化值:false
> 引用数据类型数组元素的默认初始化值:null

8. 一维数组的内存解析


8.1 Java中的内存结构是如何划分的?(主要关心JVM的运行时内存环境)
> 将内存区域划分为5个部分:程序计数器、虚拟机栈、本地方法栈、堆、方法区

> 与目前数组相关的内存结构:   比如:int[] arr = new int[]{1,2,3};
    > 虚拟机栈:用于存放方法中声明的变量。比如:arr
    > 堆:用于存放数组的实体(即数组中的所有元素)。比如:1,2,3

8.2 举例:具体一维数组的代码的内存解析

9.一维数组的相关练习

案例:输出英文星期几

用一个数组,保存星期一到星期天的7个英语单词,从键盘输入1-7,显示对应的单词
{"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}

public class ArrayExer02 {
    public static void main(String[] args) {
        //定义包含7个单词的数组
        String[] weeks = {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};

        //从键盘获取指定的数值,使用Scanner
        Scanner scan  = new Scanner(System.in);
        System.out.println("请输入数值(1-7):");
        int day = scan.nextInt();

        //针对获取的数据进行判断即可
        if(day < 1 || day > 7){
            System.out.println("你输入的数据有误。");
        }else{
            System.out.println(weeks[day - 1]);
        }

        scan.close();
    }
}

案例:学生考试等级划分

从键盘读入学生成绩,找出最高分,并输出学生成绩等级。
成绩>=最高分-10    等级为’A’
成绩>=最高分-20    等级为’B’
成绩>=最高分-30    等级为’C’
其余               等级为’D’

package com.atguigu1.one.exer3;

import java.util.Scanner;
public class ArrayExer03 {
    public static void main(String[] args) {
        //1. 从键盘输入学生的人数,根据人数,创建数组(动态初始化)
        Scanner scan = new Scanner(System.in);
        System.out.print("请输入学生人数:");
        int count = scan.nextInt();

        int[] scores = new int[count];

        //2. 根据提示,依次输入学生成绩,并将成绩保存在数组元素中
        System.out.println("请输入" + count + "个成绩");
        for (int i = 0; i < scores.length; i++) {
            scores[i] = scan.nextInt();
        }


        //3. 获取学生成绩的最大值
        int maxScore = scores[0];
        for (int i = 1; i < scores.length; i++) {
            if (maxScore < scores[i]) {
                maxScore = scores[i];
            }
        }

        System.out.println("最高分是:" + maxScore);

        //4. 遍历数组元素,根据学生成绩与最高分的差值,得到每个学生的等级,并输出成绩和等级
        for (int i = 0; i < scores.length; i++) {
            if (scores[i] >= maxScore - 10) {
                System.out.println("student " + i + " score is " + scores[i] +
                        " grade is A");
            } else if (scores[i] >= maxScore - 20) {
                System.out.println("student " + i + " score is " + scores[i] +
                        " grade is B");
            } else if (scores[i] >= maxScore - 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");
            }
        }

        scan.close();

    }
}

二维数组

1. 二维数组的理解

- 对于二维数组的理解,可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。
- 其实,从数组底层的运行机制来看,其实没有多维数组。
- 概念:数组的外层元素;数组的内层元素

2. 二维数组的使用(6个基本点)

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

> 数组的声明和初始化

//复习
		int[] arr1 = new int[]{1,2,3};
		//方式1:静态初始化:数组变量的赋值和数组元素的赋值同时进行
		int[][] arr2 = new int[][]{{1,2,3},{4,5},{6,7,8,9}};

		//方式2:动态初始化1:数组变量的赋值和数组元素的赋值分开进行
		String[][] arr3 = new String[3][4];
		//方式2:动态初始化2
		double[][] arr4 = new double[2][];

		//其它正确的写法:
		int arr5[][] = new int[][]{{1,2,3},{4,5},{6,7,8,9}};
		int[] arr6[] = new int[][]{{1,2,3},{4,5},{6,7,8,9}};
		int arr7[][] = {{1,2,3},{4,5},{6,7,8,9}}; //类型推断
		String arr8[][] = new String[3][4];

		//错误的写法
//		int[][] arr9 = new int[3][3]{{1,2,3},{4,5,6},{7,8,9}};
//		int[3][3] arr10 = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
//		int[][] arr11 = new int[][10];

> 调用数组的指定元素

        //针对于arr2来说,外层元素{1,2,3}、{4,5}、{6,7,8,9} 内层元素:1,2,3,4,5,6,7,8,9
		//调用内层元素
		System.out.println(arr2[0][0]);//1
		System.out.println(arr2[2][1]);//7

		//调用外层元素
		System.out.println(arr2[0]);//[I@776ec8df

		//测试arr3,arr4
		arr3[0][1] = "Tom";
		System.out.println(arr3[0][1]);
		System.out.println(arr3[0]);//[Ljava.lang.String;@4eec7777

		arr4[0] = new double[4];
		arr4[0][0] = 1.0;

> 数组的属性:length,表示数组的长度

        System.out.println(arr2.length);//3
		System.out.println(arr2[0].length);//3
		System.out.println(arr2[1].length);//2
		System.out.println(arr2[2].length);//4

> 数组的遍历

        for (int i = 0; i < arr2.length; i++) {
			for(int j = 0;j < arr2[i].length;j++){
				System.out.print(arr2[i][j] + "\t");
			}
			System.out.println();
		}

> 数组元素的默认初始化值

        //以动态初始化方式1说明:
		int[][] arr1 = new int[3][2];
		//外层元素默认值:
		System.out.println(arr1[0]);//[I@776ec8df
		System.out.println(arr1[1]);//[I@4eec7777
		//内层元素默认值:
		System.out.println(arr1[0][0]); //0


		boolean[][] arr2 = new boolean[3][4];
		//外层元素默认值:
		System.out.println(arr2[0]);//[Z@3b07d329
		//内层元素默认值:
		System.out.println(arr2[0][1]);//false

		String[][] arr3 = new String[4][2];
		//外层元素默认值:
		System.out.println(arr3[0]); //[Ljava.lang.String;@41629346
		//内层元素默认值:
		System.out.println(arr3[0][1]);//null

		//********************************
		//以动态初始化方式2说明:
		int[][] arr4 = new int[4][];
		//外层元素默认值:
		System.out.println(arr4[0]);//null
		//内层元素默认值:
		System.out.println(arr4[0][0]);//报错


//		String[][] arr5 = new String[5][];
//		//外层元素默认值:
//		System.out.println(arr5[0]);//null
//		//内层元素默认值:
//		System.out.println(arr5[0][0]);//报错


> 二维数组的内存解析(难)

 

3. 二维数组元素的默认初始化值


3.1 动态初始化方式1:(比如:int[][] arr = new int[3][4])

1)外层元素,默认存储地址值。
2)内层元素,默认与一维数组元素的不同类型的默认值规定相同。
    > 整型数组元素的默认初始化值:0
    > 浮点型数组元素的默认初始化值:0.0
    > 字符型数组元素的默认初始化值:0 (或理解为'\u0000')
    > boolean型数组元素的默认初始化值:false
    > 引用数据类型数组元素的默认初始化值:null

3.2 动态初始化方式2:(比如:int[][] arr = new int[3][])


1)外层元素,默认存储null
2)内层元素,不存在的。如果调用会报错(NullPointerException)

4.二维数组相关的练习

案例1:获取arr数组中所有元素的和。

提示:使用for的嵌套循环即可。

public class ArrayExer01 {
    public static void main(String[] args) {
        //初始化数组:静态初始化
        int[][] arr = new int[][]{{3,5,8},{12,9},{7,0,6,4}};

        /*
        * 不建议使用动态初始化
        * int[][] arr = new int[3][];
        * arr[0] = new int[3];
        * arr[0][0] = 3;
        * ...
        *
        * */

        int sum = 0;//记录元素的总和
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                sum += arr[i][j];
            }
        }

        System.out.println("总和为:" + sum);

    }
}

 


案例:声明:int[] x,y[]; 在给x,y变量赋值以后,以下选项允许通过编译的是:

声明:int[] x,y[]; 在给x,y变量赋值以后,以下选项允许通过编译的是: x:一维int[]   y:二维int[][]

a)    x[0] = y;             no
b)    y[0] = x;             yes
c)    y[0][0] = x;          no
d)    x[0][0] = y;          no
e)    y[0][0] = x[0];       yes
f)    x = y;                no

提示:
一维数组:int[] x  或者int x[]
二维数组:int[][] y 或者  int[] y[]  或者 int  y[][]

public class  ArrayExer02 {
    public static void main(String[] args) {
        // = :赋值符号。
        int i = 10;
        int j = i;
        byte b = (byte)i; //强制类型转换

        long l = i;//自动类型提升


        //举例:数组
        int[] arr1 = new int[10];
        byte[] arr2 = new byte[20];
//        arr1 = arr2; //编译不通过。原因:int[] 、 byte[] 是两种不同类型的引用变量

        System.out.println(arr1);
        System.out.println(arr2);

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

//        arr3 = arr1; //编译不通过。

        arr3[0] = arr1;
        System.out.println(arr3[0]);
        System.out.println(arr1);

        System.out.println(arr3);
    }
}

案例:二维数组存储数据,并遍历

String[][] employees = {
    {"10", "1", "段 誉", "22", "3000"},
    {"13", "2", "令狐冲", "32", "18000", "15000", "2000"},
    {"11", "3", "任我行", "23", "7000"},
    {"11", "4", "张三丰", "24", "7300"},
    {"12", "5", "周芷若", "28", "10000", "5000"},
    {"11", "6", "赵 敏", "22", "6800"},
    {"12", "7", "张无忌", "29", "10800","5200"},
    {"13", "8", "韦小宝", "30", "19800", "15000", "2500"},
    {"12", "9", "杨 过", "26", "9800", "5500"},
    {"11", "10", "小龙女", "21", "6600"},
    {"11", "11", "郭 靖", "25", "7100"},
    {"12", "12", "黄 蓉", "27", "9600", "4800"}
};

其中"10"代表普通职员,"11"代表程序员,"12"代表设计师,"13"代表架构师。显示效果如图。

public class ArrayExer03 {
    public static void main(String[] args) {
        //定义二维employees数组:
        String[][] employees = {
                {"10", "1", "段 誉", "22", "3000"},
                {"13", "2", "令狐冲", "32", "18000", "15000", "2000"},
                {"11", "3", "任我行", "23", "7000"},
                {"11", "4", "张三丰", "24", "7300"},
                {"12", "5", "周芷若", "28", "10000", "5000"},
                {"11", "6", "赵 敏", "22", "6800"},
                {"12", "7", "张无忌", "29", "10800","5200"},
                {"13", "8", "韦小宝", "30", "19800", "15000", "2500"},
                {"12", "9", "杨 过", "26", "9800", "5500"},
                {"11", "10", "小龙女", "21", "6600"},
                {"11", "11", "郭 靖", "25", "7100"},
                {"12", "12", "黄 蓉", "27", "9600", "4800"}
        };

        System.out.println("员工类型\t编号\t姓名\t\t年龄\t薪资\t\t奖金\t\t股票");

        for (int i = 0; i < employees.length; i++) {
            //"10"代表普通职员,"11"代表程序员,"12"代表设计师,"13"代表架构师
            String employeeType = employees[i][0];
            switch(employeeType){
                case "10":
                    System.out.print("普通职员\t");
                    break;
                case "11":
                    System.out.print("程序员\t");
                    break;
                case "12":
                    System.out.print("设计师\t");
                    break;
                case "13":
                    System.out.print("架构师\t");
                    break;
            }

            for (int j = 1; j < employees[i].length; j++) {
                System.out.print(employees[i][j] + "\t");
            }
            System.out.println();
        }

    }
}

 

数组的常见算法一

1. 数值型数组特征值统计


这里的特征值涉及到:平均值、最大值、最小值、总和等

案例:定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值,最小值,总和,平均值,
并输出出来。

要求:所有随机数都是两位数:[10,99]
提示:求[a,b]范围内的随机数: (int)(Math.random() * (b - a + 1)) + a;
public class ArrayExer01 {
    public static void main(String[] args) {
        //1. 动态初始化方式创建数组
        int[] arr = new int[10];
        //2. 通过循环给数组元素赋值
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int)(Math.random() * (99 - 10 + 1)) + 10;
            System.out.print(arr[i] + "\t");
        }

        System.out.println();

        //3.1 求最大值
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(max < arr[i]){
                max = arr[i];
            }
        }
        System.out.println("最大值为:" + max);

        //3.2 求最小值
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(min > arr[i]){
                min = arr[i];
            }
        }
        System.out.println("最小值为:" + min);


        //3.3 求总和
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        System.out.println("总和为:" + sum);

        //3.4 求平均值
        int avgValue = sum / arr.length;
        System.out.println("平均值为:" + avgValue);


    }
}
案例:评委打分

分析以下需求,并用代码实现:

(1)在编程竞赛中,有10位评委为参赛的选手打分,分数分别为:5,4,6,8,9,0,1,2,7,3

(2)求选手的最后得分(去掉一个最高分和一个最低分后其余8位评委打分的平均值)
public class ArrayExer02 {
    public static void main(String[] args) {

        int[] scores = {5,4,6,8,9,0,1,2,7,3};
        //声明三个特征值
        int sum = 0;
        int max = scores[0];
        int min = scores[0];

        for (int i = 0; i < scores.length; i++) {
            sum += scores[i]; //累加总分
            //用于获取最高分
            if(max < scores[i]){
                max = scores[i];
            }
            //用于获取最低分
            if(min > scores[i]){
                min = scores[i];
            }
        }

        int avg = (sum - max - min) / (scores.length - 2);
        System.out.println("去掉最高分和最低分之后,平均分为:" + avg);


    }
}

2. 数组元素的赋值(实际开发中,遇到的场景比较多)

案例:使用二维数组打印一个 10 行杨辉三角。

   提示:
   1. 第一行有 1 个元素, 第 n 行有 n 个元素
   2. 每一行的第一个元素和最后一个元素都是 1
   3. 从第三行开始, 对于非第一个元素和最后一个元素的元素。即:
   yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];

 

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

        //1. 创建二维数组
        int[][] yangHui = new int[10][];

        //2.使用循环结构,初始化外层数组元素
        for(int i = 0;i < yangHui.length;i++){
            yangHui[i] = new int[i + 1];
            //3. 给数组的元素赋值
            //3.1 给数组每行的首末元素赋值为1
            yangHui[i][0] = yangHui[i][i] = 1;
            //3.2 给数组每行的非首末元素赋值
            //if(i >= 2){
                for(int j = 1;j < yangHui[i].length - 1;j++){ //j从每行的第2个元素开始,到倒数第2个元素结束
                    yangHui[i][j] = yangHui[i - 1][j] + yangHui[i - 1][j - 1];
                }
            //}

        }
        //遍历二维数组
        for (int i = 0; i < yangHui.length; i++) {
            for (int j = 0; j < yangHui[i].length; j++) {
                System.out.print(yangHui[i][j] + "\t");
            }
            System.out.println();
        }


    }
}

3. 数组的复制

案例:复制、赋值

使用简单数组
(1)创建一个名为ArrayTest的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
(3)显示array1的内容。
(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
(5)打印出array1。

思考:array1和array2是什么关系?
【answer】array1和array2是两个变量,共同指向了堆空间中的同一个数组结构。即二者的地址值相同。

拓展:修改题目,实现array2对array1数组的复制

赋值

public class  ArrayExer04 {
    public static void main(String[] args) {
        //(1)创建一个名为ArrayExer04的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
        int[] array1,array2;
        //(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
        array1 = new int[]{2,3,5,7,11,13,17,19};
        //(3)显示array1的内容。
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }
        //(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
        array2 = array1;
        System.out.println();
        System.out.println(array1);
        System.out.println(array2);

        for (int i = 0; i < array2.length; i++) {
            if(i % 2 == 0){
                array2[i] = i;
            }
        }

        System.out.println();//换行
        //(5)打印出array1。
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }
    }
}

 复制

public class ArrayExer04_1 {
    public static void main(String[] args) {
        //(1)创建一个名为ArrayExer04的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
        int[] array1,array2;
        //(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
        array1 = new int[]{2,3,5,7,11,13,17,19};
        //(3)显示array1的内容。
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }
        //(4)复制array1数组给array2,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
        array2 = new int[array1.length];
        for (int i = 0; i < array1.length; i++) {
            array2[i] = array1[i];
        }

        System.out.println();
        System.out.println(array1);
        System.out.println(array2);

        for (int i = 0; i < array2.length; i++) {
            if(i % 2 == 0){
                array2[i] = i;
            }
        }

        System.out.println();//换行
        //(5)打印出array1。
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }
    }
}

 

4. 数组的反转

案例:
定义数组:int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
如何实现数组元素的反转存储?你有几种方法。

 

public class ArrayExer05 {
    public static void main(String[] args) {
        int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};

        //遍历
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
        System.out.println();

        //反转操作
        //方式1:
//        for(int i = 0;i < arr.length/2;i++){
//            //交互arr[i] 与 arr[arr.length - 1 - i]位置的元素
//            int temp = arr[i];
//            arr[i] = arr[arr.length - 1 - i];
//            arr[arr.length - 1 - i] = temp;
//        }
        //方式2:
        for(int i = 0,j = arr.length - 1;i < j;i++,j--){
            //交互arr[i] 与 arr[j]位置的元素
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }

        //方式3:不推荐
//        int[] newArr = new int[arr.length];
//        for(int i = arr.length - 1;i >= 0;i--){
//            newArr[arr.length - 1 - i] = arr[i];
//        }

//        arr = newArr;

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

数组的常见算法二

1. 数组的扩容与缩容

案例1:数组的扩容:

现有数组 int[] arr = new int[]{1,2,3,4,5};
现将数组长度扩容1倍,并将10,20,30三个数据添加到arr数组中,如何操作?
public class ArrayExer01_1 {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4,5};

        //扩容1倍容量
//        int[] newArr = new int[arr.length * 2];
        //或
        int[] newArr = new int[arr.length << 1];

        //将原有数组中的元素复制到新的数组中
        for (int i = 0; i < arr.length; i++) {

            newArr[i] = arr[i];
        }

        //将10,20,30三个数据添加到新数组中
        newArr[arr.length] = 10;
        newArr[arr.length + 1] = 20;
        newArr[arr.length + 2] = 30;

        //将新的数组的地址赋值给原有的数组变量
        arr = newArr;

        //遍历arr
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
    }
}
案例:数组的缩容:

现有数组 int[] arr={1,2,3,4,5,6,7}。现需删除数组中索引为4的元素。
public class ArrayExer01_2 {
    public static void main(String[] args) {
        int[] arr={1,2,3,4,5,6,7};

        int deleteIndex = 4;

        //方式1:不新建数组
//        for(int i = deleteIndex;i < arr.length - 1;i++){
//            arr[i] = arr[i + 1];
//        }
//
//        //修改最后元素,设置为默认值
//        arr[arr.length - 1] = 0;


        //方式2:新建数组,新的数组的长度比原有数组的长度少1个
        int[] newArr = new int[arr.length - 1];
        for (int i = 0; i < deleteIndex; i++) {
            newArr[i] = arr[i];
        }

        for(int i = deleteIndex;i < arr.length - 1;i++){
            newArr[i] = arr[i + 1];
        }

        arr = newArr;

        //遍历arr数组
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }

    }
}

2. 数组元素的查找

顺序查找(线性查找):
    > 优点:算法简单;
    > 缺点:执行效率低。执行的时间复杂度O(N)

二分法查找:
    > 优点:执行效率高。执行的时间复杂度O(logN)
    > 缺点:算法相较于顺序查找难一点;前提:数组必须有序

案例1:线性查找

定义数组:int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67};
查找元素5是否在上述数组中出现过?如果出现,输出对应的索引值。


案例2:二分法查找

定义数组:int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100};
查找元素5是否在上述数组中出现过?如果出现,输出对应的索引值。


二分法查找

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

        int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100};

        int target = 5;
//        target = 17;

        int head = 0;//默认的首索引
        int end = arr2.length - 1;//默认的尾索引


        boolean isFlag = false;//判断是否找到了指定元素

        while(head <= end){

            int middle = (head + end) / 2;

            if(target == arr2[middle]){
                System.out.println("找到了" + target + ",对应的位置为:" + middle);
                isFlag = true;
                break;
            }else if(target > arr2[middle]){
                head = middle + 1;
            }else{//target < arr2[middle]
                end = middle - 1;
            }
        }

        if(!isFlag){
            System.out.println("不好意思,未找到");
        }
    }
}

线性查找

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

        int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67};

        int target = 5;
//        target = 15;

        //查找方式:线性查找
        //方式1:
//        boolean isFlag = true;
//        for(int i = 0;i < arr1.length;i++){
//            if(target == arr1[i]){
//                System.out.println("找到了" + target + ",对应的位置为:" + i);
//                isFlag = false;
//                break;
//            }
//        }
//
//        if(isFlag){
//            System.out.println("不好意思,没有找到此元素");
//        }

        //方式2:
        int i = 0;
        for(;i < arr1.length;i++){
            if(target == arr1[i]){
                System.out.println("找到了" + target + ",对应的位置为:" + i);
                break;
            }

        }

        if(i == arr1.length){
            System.out.println("不好意思,没有找到此元素");
        }


    }
}

3. 数组的排序

注意,经常将以2为底n的对数简写成logn。

排序算法的衡量标准:① 时间复杂度(最重要) ② 空间复杂度 ③ 稳定性
Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n<sup>2</sup>)<Ο(n<sup>3</sup>)<…<Ο(2<sup>n</sup>)<Ο(n!)<O(n<sup>n</sup>)

排序的分类:内部排序(内存中排序);外部排序(外部存储设备+内存)

内部排序的具体算法:10种。具体的见课件

我们需要关注的几个排序算法:

> 冒泡排序:最简单,需要大家会手写。时间复杂度:O(n^2)
> 快速排序:最快的,开发中默认选择的排序方式;掌握快速排序的实现思路;时间复杂度:

O(n(logn))

1:使用冒泡排序,实现整型数组元素的排序操作

比如:int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
public class BubbleSortTest {
    public static void main(String[] args) {
        int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};

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

        //冒泡排序,实现数组元素从小到大排列
        for(int j = 0;j < arr.length - 1;j++){
            for (int i = 0; i < arr.length - 1 - j; i++) {
                if(arr[i] > arr[i + 1]){
                    //交互arr[i] 和 arr[i + 1]
                    int temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                }

            }
        }

        System.out.println();
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
    }
}
案例:使用快速排序,实现整型数组元素的排序操作

比如:int[] data = { 9, -16, 30, 23, -30, -49, 25, 21, 30 };
public class QuickSort {
	public static void main(String[] args) {
		int[] data = {9, -16, 30, 23, -30, -49, 25, 21, 30};
		System.out.println("排序之前:");
		for (int i = 0; i < data.length; i++) {
			System.out.print(data[i]+" ");
		}

		quickSort(data);//调用实现快排的方法

		System.out.println("\n排序之后:");
		for (int i = 0; i < data.length; i++) {
			System.out.print(data[i]+" ");
		}
	}

	public static void quickSort(int[] data) {
		subSort(data, 0, data.length - 1);
	}

	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) {
					//交换data数组[low]与[high]位置的元素
					swap(data, low, high);
				} else {
					break;
				}
			}
			//交换data数组[start]与[high]位置的元素
			swap(data, start, high);

			//经过代码[start, high)部分的元素 比[high, end]都小

			//通过递归调用,对data数组[start, high-1]部分的元素重复刚才的过程
			subSort(data, start, high - 1);
			//通过递归调用,对data数组[high+1,end]部分的元素重复刚才的过程
			subSort(data, high + 1, end);
		}
	}

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

数组工具类Arrays的使用

1. Arrays类所在位置: 处在java.util包下

2. 作用:
java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。

public class ArraysTest {
	public static void main(String[] args) {
		//1. boolean equals(int[] a,int[] b):比较两个数组的元素是否依次相等
		int[] arr1 = new int[]{1,2,3,4,5};
		int[] arr2 = new int[]{1,2,3,4,5};
		arr2 = new int[]{1,2,3,5,4};

		System.out.println(arr1 == arr2);

		boolean isEquals = Arrays.equals(arr1,arr2);
		System.out.println(isEquals);//true ---> false


		//2. String toString(int[] a):输出数组元素信息。
		System.out.println(arr1); //[I@776ec8df

		System.out.println(Arrays.toString(arr1));


		//3.void fill(int[] a,int val):将指定值填充到数组之中。
		Arrays.fill(arr1,10);

		System.out.println(Arrays.toString(arr1));

		//4. void sort(int[] a):使用快速排序算法实现的排序
		int[] arr3 = new int[]{34,54,3,2,65,7,34,5,76,34,67};
		Arrays.sort(arr3);

		System.out.println(Arrays.toString(arr3));

		//5. int binarySearch(int[] a,int key):二分查找
		//使用前提:当前数组必须是有序的
		int index = Arrays.binarySearch(arr3,15);
		if(index >= 0){
			System.out.println("找到了,索引位置为:" + index);
		}else{
			System.out.println("未找到");
		}



	}
}

数组的使用中常见的异常小结

> 数组角标越界的异常:ArrayIndexOutOfBoundsException
> 空指针的异常:NullPointerException

 出现异常会怎样?如何处理?

> 一旦程序执行中出现了异常,程序就会终止执行。
> 针对异常提供的信息,修改对应的代码,避免异常再次出现。

public class ArrayExceptionTest {
	public static void main(String[] args) {
		// 1. 数组角标越界的异常:
		int[] arr = new int[10];
		//角标的有效范围:0、1、2、...、9
//		System.out.println(arr[10]);
//		System.out.println(arr[-1]);

		// 2. 空指针异常:
		//情况1:
//		int[] arr1 = new int[10];
//
//		arr1 = null;
//
//		System.out.println(arr1[0]);//NullPointerException

		//情况2:
//		int[][] arr2 = new int[3][];
//
		arr2[0] = new int[10];//此行代码不存在时,下一行代码出现NullPointerException
//
//		System.out.println(arr2[0][1]); //NullPointerException


		//情况3:
//		String[] arr3 = new String[4];
//		System.out.println(arr3[0].toString());//NullPointerException

	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值