【Java基础系列教程】第五章 Java数组详解

一、数组概述

1.1 为什么需要数组

        如果说现在要求你定义100个整型变量,那么如果按照之前的做法,可能现在定义的的结构如下:
        int i1, i2, i3, ... i100;

        但是这个时候如果按照此类方式定义就会非常麻烦,因为这些变量彼此之间没有任何的关联,也就是说如果现在突然再有一个要求,要求你输出这100个变量的内容,意味着你要编写System.out.println()语句100次。

        如何解决这个问题,Java语言提供了数组(Array)的数据结构,是一个容器可以存储相同数据类型的元素,可以将100个数存储到数组中。

/*
 * 为什么要使用数组?
 * */
public class ArrayTest01 {
    public static void main(String[] args) {
        /*
         * 为什么要定义数组:
         *   比如我们定义一批数据的时候,无论是存,还是取都非常麻烦; (10000)
         *   i1 - i10000 存: 向内存存储, 有10000个变量名 和 10000个变量值;1、非常浪费内存
         *   i1 - i10000 取: 从内存中取值,比如打印输出,10000次输出语句; 2、代码复用性低
         *
         * */
        int i1 = 1;
        int i2 = 2;
        int i3 = 3;
        int i4 = 4;
        int i5 = 5;

        for (int i = 1; i <= 5; i++) {
            // 我们要输出i1 - i5变量对应的值
            System.out.println("i" + i); //i1 - i5,输出的是i1-i5的字符串
            //System.out.println("i1");
            //System.out.println(i1); // 调用变量值
        }

        /*
         * 如果要存储有关联的一批次的数据
         *   商品1: 图片1,辣椒炒肉,18.5,1200
         *   商品2: 图片2,西红柿鸡蛋,8.5,1500
         * 3、变量之间的关联是松散的,不便于集中管理,不符合命名规范
         * */
        String goodsImg1 = "images/XX.jpg";
        String goodsName1 = "辣椒炒肉";
        double goodsPrice1 = 18.5;
        int goodsSale1 = 1200;

        String goodsImg2 = "images/YY.jpg";
        String goodsName2 = "西红柿鸡蛋";
        double goodsPrice2 = 8.5;
        int goodsSale2 = 1500;

        /*
         * 总结:
         *   1、通过一个数组名,可以存储n个值,节省内存空间
         *   2、在我们遍历数据的时候,可以通过循环结合下标来快速实现遍历,提高代码复用性
         *   3、数组存储数据,让我们数据便于集中管理,加强数组的关联性;
         * */
    }
}

1.2 深入理解数组概念

数组概述:

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

数组相关概念:

        数组名:数组的名称,用于区分不同的数组,数组只有一个名称,即标识符,要符合标识符规范。
        元素类型:数组要存储的元素的数据类型。
        数组元素:向数组中存放的数据/元素。
        元素下标:对数组元素进行编号,元素下标标明了元素在数组中的位置,从0开始;数组中的每个元素都可以通过下标来访问。
        数组长度:数组长度固定不变,避免数组越界。

数组的特点:

        数组是有序排列的集合。
        数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。
        数组的元素的类型,必须一样。
        创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址。
        数组的长度是固定的,长度一旦确定,就不能修改。 
        我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。

数组的分类:

        按照维数:一维数组、二维数组、三维数组、...
                注: 从二维数组开始,我们都称之为多维数组。

        按照数组元素的类型:基本数据类型元素的数组、引用数据类型元素的数组(即对象数组)。

二、一维数组的使用

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

声明数组的语法格式1:
        元素类型[] 数组名 = new 元素类型[元素个数或数组长度];

声明数组的语法格式2:
        元素类型[] 数组名 = new 元素类型[]{元素,元素,……};

声明一个变量就是在内存空间划出一块合适的空间,声明一个数组就是在内存空间划出一串连续的空间。

注:
        []在元素类型后 或 数组名后都可以。
        Java语言中声明数组时不能指定其长度(数组中元素的数), 例如: int a[5]; //非法

数组初始化分类:
        动态初始化:数组声明且为数组元素分配空间与赋值的操作分开进行
                int[] arr = new int[3];
                arr[0] = 3;
                arr[1] = 9;
                arr[2] = 8
    
        静态初始化:在定义数组的同时就为数组元素分配空间并赋值。
                int arr[] = new int[]{ 3, 9, 8}; 或 int[] arr = {3,9,8};

new关键字:
        Java中使用关键字new来创建数组。
        定义并用运算符new为之分配空间后,才可以引用数组中的每个元素;

示例代码:

public class LinearArrayTest01 {
    public static void main(String[] args) {
        // 变量声明
        int num;
        // 变量初始化
        num = 10;
        // 变量声明 + 初始化
        int id = 1001;

        // 数组声明
        int[] ids;
        // 静态初始化:数组的初始化和数组元素的赋值操作同时进行
        ids = new int[]{1001, 1002, 1003, 1004};
        // 动态初始化:数组的初始化和数组元素的赋值操作分开进行
        String[] names = new String[5];

        // 错误的写法:
        // int[] arr1 = new int[];
        // int[5] arr2 = new int[5];
        // int[] arr3 = new int[3]{1,2,3};

        //也是正确的写法:
        int[] arr4 = {1, 2, 3, 4, 5};// 类型推断

        // 总结:数组一旦初始化完成,其长度就确定了。
    }
}

2.2 一维数组的使用

        数组元素的引用方式:数组名[数组元素下标],如boy[0],boy[1]等。
                数组元素下标可以是整型常量或整型表达式。如a[3] , b[i] , c[6*i];
                数组元素下标从0开始;长度为n的数组合法下标取值范围: 0 —>n-1;如int a[]=new int[3]; 可引用的数组元素为a[0]、a[1]、a[2]

        需要注意的是索引从0开始,到数组的长度-1结束。

示例代码:

public class LinearArrayTest02 {
    public static void main(String[] args) {
        // 创建一个长度为5的数组,用来存储学生的姓名
        String[] names = new String[5];

        // 给数组的指定位置赋值
        names[0] = "张三";
        names[1] = "李四";
        names[2] = "王五";
        names[3] = "马六";
        names[4] = "田七";
        // 数组长度5,下标从0开始,到4结束,使用下标5会抛出异常。
        // names[5] = "钱八";

        // 调用数组的指定位置的元素
        System.out.println("下标2的学生的姓名是:" + names[2]);
    }
}

2.3 获取数组的长度

        每个数组都有一个属性length指明它的长度,例如:a.length 指明数组a的长度(元素个数)。

        数组一旦初始化,其长度是不可变的。

示例代码:

public class LinearArrayTest03 {
    public static void main(String[] args) {
        int[] ids = new int[]{1001, 1002, 1003, 1004};
        String[] names = new String[5];

        System.out.println(names.length);// 5
        System.out.println(ids.length);// 4
    }
}

2.4 一维数组的遍历

        通过for循环,结合下标索引实现数组的遍历。

示例代码:

public class LinearArrayTest04 {
    public static void main(String[] args) {
        String[] names = {"张三", "李四", "王五", "马六", "田七"};
        /*System.out.println(names[0]);
        System.out.println(names[1]);
        System.out.println(names[2]);
        System.out.println(names[3]);
        System.out.println(names[4]);
        */

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

增强for循环:

        foreach语句是java5的新特征之一,在遍历数组、集合方面,foreach为开发人员提供了极大的方便。
        foreach语句是for语句的特殊简化版本,但是foreach语句并不能完全取代for语句,然而,任何的foreach语句都可以改写为for语句版本。

        foreach的语句格式:
                for(元素类型 元素变量x : 数组/集合){
                        引用了x的java语句;
                }

public class LinearArrayTest05 {
    public static void main(String[] args) {
        String[] names = {"张三", "李四", "王五", "马六", "田七"};

        for (String name : names) {
            System.out.println(name);
        }
    }
}

练习题:

        对数据进行处理:计算5位学生的平均分

public class LinearArrayTest06 {
    public static void main(String[] args) {
        int[] score = {60, 80, 90, 70, 85};
        double avg;
        avg = (score[0] + score[1] + score[2] + score[3] + score[4]) / 5;

        // 上述写法虽说也可以实现,但是如果10个或100个学生呢?
    }
}
public class LinearArrayTest07 {
    public static void main(String[] args) {
        // 通过遍历数组叠加求和,最后除以数组长度得到平均分。
        int[] score = {60, 80, 90, 70, 85};
        int sum = 0;
        for (int i = 0; i < score.length; i++) {
            sum += score[i];
        }
        double avg = sum / score.length;
    }
}

2.5 数组元素的默认初始值

        数组是引用类型,它的元素相当于类的成员变量,因此数组一经分配空间,其中的每个元素也被按照成员变量同样的方式被隐式初始化。
    
        对于基本数据类型而言,默认初始化值各有不同。
        对于引用数据类型而言,默认初始化值为null(注意与0不同!)

数组元素类型 元素默认初始值
byte 0
short 0
int 0
long 0L
float 0.0F
double 0.0
char 0 或写为:’\u0000’(表现为空)
boolean false
引用类型 null

示例代码:

public class LinearArrayTest08 {
    public static void main(String[] args) {
        int[] arr = new int[4];
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        System.out.println("------------------------");

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

        System.out.println("------------------------");
        char[] arr3 = new char[4];
        for (int i = 0; i < arr3.length; i++) {
            System.out.println("----" + arr3[i] + "----");
        }

        if (arr3[0] == 0) {
            System.out.println("char类型的默认值是0,但是表现为空");
        }

        System.out.println("------------------------");
        boolean[] arr4 = new boolean[5];
        System.out.println(arr4[0]);

        System.out.println("------------------------");
        String[] arr5 = new String[5];
        System.out.println(arr5[0]);
        if (arr5[0] == null) {
            System.out.println("引用类型的默认类型是null,不是null字符串!");
        }
    }
}

2.6 一维数组的内存解析

内存的简化结构:

        栈(stack):存放基本类型的变量数据、局部变量和对象的引用,但对象本身不存放在栈中。

        堆(heap):存放由new创建的对象和数组以及对象的实例变量。

        静态存储区(static storage):又叫方法区:包含的都是在整个程序中永远唯一的元素,如class,static变量。
        常量存储区(constant storage):常量值通常直接存放在程序代码内部,这样做是安全的,因为它们永远不会被改变。
        静态区/静态域(static storage):随着类的加载而加载并初始化,存在于方法区内存中的字节码文件的静态区域中。

【Java基础系列教程】第五章 Java数组详解_第1张图片

 内存解析:

【Java基础系列教程】第五章 Java数组详解_第2张图片

        我们设定代码运行在main()中。
    
        第一行代码:int[] ids = new int[4]; ids位于main()中,属于局部变量,存储在栈空间;new int[4],new 出来的都是存储在堆空间,并且开辟四个连续的区域存储默认值;把new出来的数组的首地址赋值给栈空间的ids变量;

        第二到四行代码:覆盖数组的默认初始值;
    
        第五行代码:String[] names = {...},虽说是静态赋值,但是流程和第一行代码类似,只是创建完数组就把默认值给覆盖了;

        第六行代码:覆盖names数组下标1的值;

        第七行代码:在堆内存中开辟两个连续的区域存储默认值,把新数组的首地址赋值给names,然后使用小黑、小明覆盖默认初始值;
                注:字符串值其实不会存储在图上的位置,而是放在常量池,这个暂且不解析;

        第八行代码:当我们调用names[0]的时候,肯定不会找0x2222,而是找0x3333,因为0x2222没有任何变量指向它,就会在某个不确定的时间被jvm回收。还要注意的是:当main()执行完毕,names-》ids出栈,0x3333和0x1111就没有任何变量指向它,也会在某个不确定的时间被jvm回收。

地址引用:

        数组属于引用型变量,因此两个相同类型的数组且具有相同的引用,它们就有完全相同的元素。

  例如,对于int a[] = {1,2,3}, b[ ]= {4,5};数组变量a和b分别存放着引用0x35ce36和0x757aef。 

【Java基础系列教程】第五章 Java数组详解_第3张图片

        如果使用了下列赋值语句(a和b的类型必须相同)a=b;那么,a中存放的引用和b的相同,这时系统将释放最初分配给数组a的元素,使得a的元素和b的元素相同。

【Java基础系列教程】第五章 Java数组详解_第4张图片

三、多维数组的使用

        Java 语言里提供了支持多维数组的语法。

        如果说可以把一维数组当成几何中的线性图形,那么二维数组就相当于是一个表格,像Excel中的表格一样。

        二维数组本质上是以数组作为数组元素的数组,即“数组的数组”,其实,从数组底层的运行机制来看,其实没有多维数组。

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

声明二位数组的语法格式1(动态初始化):int[][] arr = new int[3][2];
        定义了名称为arr的二维数组
        二维数组中有3个一维数组
        每一个一维数组中有2个元素
        一维数组的名称分别为arr[0], arr[1], arr[2]
        给第一个一维数组1下标位赋值为78写法是:arr[0][1] = 78;

声明二位数组的语法格式1(动态初始化):int[][] arr = new int[3][];
        二维数组中有3个一维数组。
        每个一维数组都是默认初始化值null (注意:区别于格式1)
        可以对这个三个一维数组分别进行初始化
        arr[0] = new int[3]; arr[1] = new int[1]; arr[2] = new int[2];
        注:
                int[][]arr = new int[][3]; //非法

声明二位数组的语法格式3(静态初始化):int[][] arr = new int[][]{{3,8,2},{2,7},{9,0,1,6}};
        定义一个名称为arr的二维数组,二维数组中有三个一维数组
        每一个一维数组中具体元素也都已初始化
        第一个一维数组 arr[0] = {3,8,2};
        第二个一维数组 arr[1] = {2,7};
        第三个一维数组 arr[2] = {9,0,1,6};
        第三个一维数组的长度表示方式:arr[2].length;

注意特殊写法情况:int[] x,y[]; x是一维数组,y是二维数组。
Java中多维数组不必都是规则矩阵形式。

示例代码:

public class MultiArrayTest01 {
    public static void main(String[] args) {
        // 二维数组的声明和初始化
        int[] arr = new int[]{1, 2, 3};//一维数组
        // 静态初始化
        int[][] arr1 = new int[][]{{1, 2, 3}, {4, 5}, {6, 7, 8}};
        // 动态初始化1
        String[][] arr2 = new String[3][2];
        // 动态初始化2
        String[][] arr3 = new String[3][];

        // 错误的情况 
        // String[][] arr4 = new String[][4];
        // String[4][3] arr5 = new String[][];
        // int[][] arr6 = new int[4][3]{{1,2,3},{4,5},{6,7,8}};

        //也是正确的写法:
        int[] arr4[] = new int[][]{{1, 2, 3}, {4, 5, 9, 10}, {6, 7, 8}};
        int[] arr5[] = {{1, 2, 3}, {4, 5}, {6, 7, 8}};
    }
}

3.2 二维数组的使用

        数组元素的引用方式:数组名[一维数组下标][二维数组下标],如boy[0][1],boy[1][1]等。

        需要注意的是索引从0开始,到数组的长度-1结束。

示例代码:

public class MultiArrayTest02 {
    public static void main(String[] args) {
        int[][] arr1 = new int[][]{{1, 2, 3}, {4, 5}, {6, 7, 8}};

        String[][] arr2 = new String[3][2];

        String[][] arr3 = new String[3][];

        System.out.println(arr1[0][1]);// 2
        System.out.println(arr2[1][1]);// null

        // 这样调用报错,因为没有给arr3[1]进行赋值操作,出现空指针异常
        // System.out.println(arr3[1][0]);
        arr3[1] = new String[4];
        System.out.println(arr3[1][0]);
    }
}

3.3 获取数组的长度

示例代码:

public class MultiArrayTest03 {
    public static void main(String[] args) {
        int[] arr4[] = new int[][]{{1, 2, 3}, {4, 5, 9, 10}, {6, 7, 8}};
        System.out.println(arr4.length);// 3
        System.out.println(arr4[0].length);// 3
        System.out.println(arr4[1].length);// 4
    }
}

3.4 二维数组的遍历

规定:二维数组分为外层数组的元素,内层数组的元素
        int[][] arr = new int[4][3];
        外层元素:arr[0],arr[1]等
        内层元素:arr[0][0],arr[1][2]等
        System.out.println(arr[0]);//[I@15db9742 
        System.out.println(arr[0][0]);//0

示例代码:

public class MultiArrayTest04 {
    public static void main(String[] args) {
        //声明二维数组并赋值	int arr[][] = {{},{},{}}
        int arr[][] = {{1, 2, 3}, {11, 12, 13, 14}, {22, 33, 44, 55, 66, 77}, {1}};

        // arr  是数组
        // arr[i]	还是数组
        for (int i = 0; i < arr.length; i++) {
            int ewArr[] = arr[i]; //二维数组里面的每个数组
            for (int j = 0; j < ewArr.length; j++) {
                System.out.print(ewArr[j] + "\t");
            }
            System.out.println();
        }

        System.out.println("--------------------------------");

        // 增强for循环遍历
        for (int ewArr[] : arr) {
            for (int x : ewArr) {
                System.out.print(x + "\t");
            }
            System.out.println();
        }
    }
}

3.5 数组元素的默认初始值

        针对于初始化方式一:比如:int[][] arr = new int[4][3];
                外层元素的初始化值为:地址值
                内层元素的初始化值为:与一维数组初始化情况相同
        
        针对于初始化方式二:比如:int[][] arr = new int[4][];
                外层元素的初始化值为:null

示例代码:

public class MultiArrayTest05 {
    public static void main(String[] args) {
        int[][] arr = new int[4][3];
        System.out.println(arr[0]);//[I@15db9742 
        System.out.println(arr[0][0]);//0

        // System.out.println(arr);//[[I@6d06d69c

        System.out.println("*****************");
        float[][] arr1 = new float[4][3];
        System.out.println(arr1[0]);//地址值
        System.out.println(arr1[0][0]);//0.0

        System.out.println("*****************");

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

        System.out.println("*****************");
        double[][] arr3 = new double[4][];
        System.out.println(arr3[1]);//null
        // System.out.println(arr3[1][0]);//报错
    }
}

3.6 二位数组的内存解析

【Java基础系列教程】第五章 Java数组详解_第5张图片

【Java基础系列教程】第五章 Java数组详解_第6张图片

四、基于数组的常见算法

4.1 数组元素的赋值

练习题1:

        杨辉三角,是二项式系数在三角形中的一种几何排列。在欧洲,这个表叫做帕斯卡三角形。帕斯卡是在1654年发现这一规律的,比杨辉要迟393年,比贾宪迟600年。杨辉三角是中国古代数学的杰出研究成果之一,它把二项式系数图形化,把组合数内在的一些代数性质直观地从图形中体现出来,是一种离散型的数与形的结合 。

        使用二维数组打印一个 10 行杨辉三角。 
        【提示】
                1. 第一行有 1 个元素, 第 n 行有 n 个元素
                2. 每一行的第一个元素和最后一个元素都是 1
                3. 从第三行开始, 对于非第一个元素和最后一个元素的元素。即:
                yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];

【Java基础系列教程】第五章 Java数组详解_第7张图片

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];

            // 给首末元素赋值
            yangHui[i][0] = yangHui[i][i] = 1;
            // 给每行的非首末元素赋值
            if(i > 1){
                for(int j = 1;j < yangHui[i].length - 1;j++){
                    yangHui[i][j] = yangHui[i-1][j-1] + yangHui[i-1][j];
                }
            }
        }
        
        // 3、遍历二维数组
        for(int i = 0;i < yangHui.length;i++){
            for(int j = 0;j < yangHui[i].length;j++){
                System.out.print(yangHui[i][j] + "  ");
            }
            System.out.println();
        }
    }
}

练习题2:

        创建一个长度为6的int型数组,要求取值为1-30,同时元素值各不相同

public class ArrayRandom {
    public static void main(String[] args) {
        int[] arr = new int[6];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) (Math.random() * 30) + 1;

            for (int j = 0; j < i; j++) {
                if (arr[i] == arr[j]) {
                    i--;
                    break;
                }
            }
        }

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

4.2 数组元素的最大/最小值、平均数、总和

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

import java.util.Scanner;

public class ArrayOperation {
    public static void main(String[] args) {
        int[] arr = new int[10];

        // 随机10 - 99的整数
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) (Math.random() * (100 - 10) + 10);
        }

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

        // 求数组元素的最大值
        int maxValue = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (maxValue < arr[i]) {
                maxValue = arr[i];
            }
        }
        System.out.println("最大值为:" + maxValue);

        // 求数组元素的最小值
        int minValue = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (minValue > arr[i]) {
                minValue = arr[i];
            }
        }
        System.out.println("最小值为:" + minValue);

        // 求数组元素的总和
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        System.out.println("总和为:" + sum);
        
        // 求数组元素的平均数
        int avgValue = sum / arr.length;
        System.out.println("平均数为:" + avgValue);
    }
}

4.3 数组复制

    使用简单数组
        (1)创建一个名为ArrayCopy的类,在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)。打印出array1。
        思考:array1和array2是什么关系?

public class ArrayCopy {
    public static void main(String[] args) {  //alt + /
        int[] array1, array2;

        array1 = new int[]{2, 3, 5, 7, 11, 13, 17, 19};

        //显示array1的内容
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }

        //赋值array2变量等于array1
        //不能称作数组的复制。
        array2 = array1;

        //修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)
        for (int i = 0; i < array2.length; i++) {
            if (i % 2 == 0) {
                array2[i] = i;
            }

        }
        System.out.println();

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

        // array1和array2是什么关系?array1和array2地址值相同,都指向了堆空间的唯一的一个数组实体。
    }
}

解析:

【Java基础系列教程】第五章 Java数组详解_第8张图片

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

public class ArrayCopy {
    public static void main(String[] args) {  //alt + /
        int[] array1, array2;

        array1 = new int[]{2, 3, 5, 7, 11, 13, 17, 19};

        //显示array1的内容
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }

        //数组的复制:
        array2 = new int[array1.length];
        for (int i = 0; i < array2.length; i++) {
            array2[i] = array1[i];
        }


        //修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)
        for (int i = 0; i < array2.length; i++) {
            if (i % 2 == 0) {
                array2[i] = i;
            }

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

【Java基础系列教程】第五章 Java数组详解_第9张图片

4.4 数组反转

        把如下数组进行反转:
        String arr[] = new String[]{"AA","BB","CC","DD","EE","FF","GG"};

public class ArrayReverse01 {
    public static void main(String[] args) {
        String arr[] = new String[]{"AA", "BB", "CC", "DD", "EE", "FF", "GG"};

        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; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
    }
}
public class ArrayReverse02 {
    public static void main(String[] args) {
        String arr[] = new String[]{"AA", "BB", "CC", "DD", "EE", "FF", "GG"};

        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] + "\t");
        }
    }
}

4.5 数组查找

4.5.1 线性查找

        线性查找又叫顺序查找,就是遍历整个列表,逐个元素与给定值比较,若某个元素和给定值相等,则查找成功。如果直到最后一个元素和给定值比较都不相等,则查找失败。

public class ArraySequentialSearch {
    public static void main(String[] args) {
        String arr[] = new String[]{"AA", "BB", "CC", "DD", "EE", "FF", "GG"};

        String findStr = "BB";
        findStr = "QQ";

        boolean isFlag = true;

        for(int i = 0;i < arr.length;i++){
            if(findStr.equals(arr[i])){
                System.out.println("找到了指定的元素,位置为:" + i);
                isFlag = false;
                break;
            }
        }
        if(isFlag){
            System.out.println("很遗憾,没有找到你要查询的元素!");
        }
    }
}

4.5.2 二分查找

        什么是二分查找呢?二分查找的基本思想是:在有序表中,取中间元素作为比较对象,若给定值与中间元素相等,则查找成功;若给定值小于中间元素,则在中间元素的左半区继续查找;若给定值大于中间元素,则在中间元素的右半区继续查找。不断重复上述过程,直到找到为止。

        从二分查找的定义我们可以看出,使用二分查找有两个前提条件:
        (1)待查找的列表必须有序。
        (2)必须使用线性表的顺序存储结构来存储数据。

        接下来我们来介绍一下折半查找的原理,并自己用代码实现折半查找。

在查找前对数组进行折半操作 (初始化指针位置)

        折半公式 =  (最大索引+最小索引)/ 2

        首先我们可以利用指针思想,假设有一个指针指向最大值(MAX),有一个指针指向最小值(MIN),还有一个指针指向的是最大值和最小值之间的索引(MID)。我把这个过程称为初始化指针位置.

【Java基础系列教程】第五章 Java数组详解_第10张图片

 折半后的指针索引和被查找元素比较

        若被查找元素的值(12)大于中间索引上的值(10),我们就把最小值指针(MIN)移动到中间指针(MID)索引的下一个索引位置,如下图:

【Java基础系列教程】第五章 Java数组详解_第11张图片

 若没有匹配到就继续折半后的指针索引和被查找元素比较。

【Java基础系列教程】第五章 Java数组详解_第12张图片

         若被查找元素的值(12)小于中间索引上的值(15),我们就把最大值指针(MAX)移动到中间指针(MID)索引的上一个索引位置,如下图:

【Java基础系列教程】第五章 Java数组详解_第13张图片

 若没有匹配到就继续折半后的指针索引和被查找元素比较

        若被查找元素的值(12)小于中间索引上的值(13),我们就把最大值指针(MAX)移动到中间指针(MID)索引的上一个索引位置,如下图:

【Java基础系列教程】第五章 Java数组详解_第14张图片

 若没有匹配到就继续折半后的指针索引和被查找元素比较。

        当小指针(MIN)的索引(4)超过了大指针(MAX)的索引(3)时,就需要停止查找了,如果真有这种情况发生,说明没有查到被查找元素的值(12),此时会返回一个负数(-1),当然如果查找到了就返回其在数组中的索引即可。

【Java基础系列教程】第五章 Java数组详解_第15张图片

 数组的折半查找代码实现

public class ArrayBinarySearch {
    public static void main(String[] args) {
        int[] arr = new int[]{1, 4, 7, 10, 13, 15, 21, 25};

        int findNum = 21;

        // 初始的最小索引
        int min = 0;

        // 初始的末索引
        int max = arr.length - 1;

        boolean isFlag = true;
        while (min <= max) {

            int mid = (min + max) / 2;

            if (findNum == arr[mid]) {
                System.out.println("找到了指定的元素,位置为:" + mid);
                isFlag = false;
                break;
            } else if (arr[mid] > findNum) {
                max = mid - 1;
            } else {//arr[middle] < findNum
                min = mid + 1;
            }
        }

        if (isFlag) {
            System.out.println("很遗憾,没有找到你要查询的元素!");
        }
    }
}

4.6 数组排序

4.6.1 冒泡排序

冒泡概述

        冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。

        它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

        这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。

实现原理

        1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。 
        2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。  
        3.针对所有的元素重复以上的步骤,除了最后一个。  
        4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

实现思路

        (1)第一次比较:首先比较第一和第二个数,将小数放在前面,将大数放在后面。

        (2)比较第2和第3个数,将小数 放在前面,大数放在后面。

    ......

        (3)如此继续,知道比较到最后的两个数,将小数放在前面,大数放在后面,重复步骤,直至全部排序完成

        (4)在上面一趟比较完成后,最后一个数一定是数组中最大的一个数,所以在比较第二趟的时候,最后一个数是不参加比较的。

        (5)在第二趟比较完成后,倒数第二个数也一定是数组中倒数第二大数,所以在第三趟的比较中,最后两个数是不参与比较的。

        (6)依次类推,每一趟比较次数减少依次

【Java基础系列教程】第五章 Java数组详解_第16张图片

实例解析

        排序数组:[10,1,35,61,89,36,55]

【Java基础系列教程】第五章 Java数组详解_第17张图片

冒泡代码

/*
* 使用冒泡排序实现升序排列
* 冒泡排序(升序)的原理:
* 	两两比较,如果前面的值比后面的值大,则交换位置
* 	外层i	0		1		2		3		4
* 原数组	第一轮	第二轮	第三轮	第四轮	第五轮	外层循环5次     arr.length-1   6 - 1
* 98		78		56		44		23		6
* 78		56		44		23		6		23
* 56		44		23		6		44		44
* 44		23		6		56		56		56
* 23		6		78		78		78		78
* 6		98		98		98		98		98
* 					
* 次数		5		4		3		2		1	
* 内层		arr.length-1-i	
* 第一轮得到一个最大值,这个最大值 
* 1.外层循环初始变量i为0,判断依据 i < arr.length - 1
* 2.内存循环初始边框j为0,判断依据 j < arr.length - i - 1
* 3.判断谁大或谁小,然后交换位置
*/
int arr[] = {32,5,100,9,78,1};
for(int i = 0;i < arr.length - 1;i++) { //用来决定轮数  5
    for(int j = 0; j < arr.length - i -1;j++) { //用来决定每轮比较的次数
        if(arr[j] > arr[j+1]) {
            //temp保存哪个值无所谓,但是保存哪个值,就要先给哪个值赋值
            int temp = arr[j+1];
            arr[j+1] = arr[j];
            arr[j] = temp;
        }
    }
}
System.out.println("冒泡升序排列之后:"+Arrays.toString(arr));

4.6.2 选择排序

        选择排序(Selection sort)是一种简单直观的排序算法。
    
        它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。

实例解析

【Java基础系列教程】第五章 Java数组详解_第18张图片

        第1趟比较:拿第1个元素依次和它后面的每个元素进行比较,如果第1个元素大于后面某个元素,交换它们,经过第1趟比较,数组中最小的元素被选出,它被排在第一位
    
        第2趟比较:拿第2个元素依次和它后面的每个元素进行比较,如果第2个元素大于后面某个元素,交换它们,经过第2趟比较,数组中第2小的元素被选出,它被排在第二位
    
        ......
    
        第n-1趟比较:第n-1个元素和第n个元素作比较,如果第n-1个元素大于第n个元素,交换它们.

选择代码

/*
* 选择排序 - 升序排列:
* 	使用指定位置的值,跟所有的值进行比较;如果前面的值大于后面的值,则交换位置
* 
* 外层循环变量 0		1		2		3	
* 原数组	第一轮	第二轮	第三轮	第四轮		比较了四次,外层循环	arr.length - 1
* 120		10		10		10		10
* 89		120		18		18		18
* 32		89		120		32		32
* 18		32		89		120		89
* 10		18		32		89		120
* 
* 次数		4		3		2		1		看似: arr.length - i - 1
* 
* 1. 外层循环初始变量i为0,小于arr.length - 1
* 2. 内层循环初始变量j为i,小于arr.length - 1
* 		j = 0		< 4
* 		j = 1		< 4
* 		j = 2		< 4
*/
int arr[] = {32,2,78,6,44,100};
for(int i = 0;i < arr.length - 1;i++) {
    for(int j = i; j < arr.length - 1;j++) {
        /*
		* i = 0  arr[i] = 2
		* j = 0  32  2 --> 2 arr[j+1] = 32
		*/
        if(arr[i] > arr[j+1]) {
            int temp = arr[j+1];
            arr[j+1] = arr[i];
            arr[i] = temp;
        }
    }
}
System.out.println("选择排序之后的数组:"+Arrays.toString(arr));

五、Arrays类

5.1 Arrays类的简介

        所在包:java.util.Arrays

        类的定义:
                public class Arrays extends Object

        此类包含用来操作数组(比如排序和搜索)的各种方法。此类还包含一个允许将数组作为列表来查看的静态工厂。 

        除非特别注明,否则如果指定数组引用为 null,则此类中的方法都会抛出 NullPointerException。 

        Arrays类里面的方法全部都是静态方法;

5.2 Arrays方法介绍

5.2.1 数组转换列表

        static List asList(T... a)     返回一个受指定数组支持的固定大小的列表。 

        Arrays.asList的作用是将数组转化为list,一般是用于在初始化的时候,设置几个值进去,简化代码,省去add的部分。

        参数:
                1、直接定义n个具体的数据。
                2、传递非基本数据类型的数组,如果是基本数据类型,那么使用包装类数组。
                也可以是数组[但是数组类型不能是(byte,short,int,long,float,double,boolean),如果是基本数据类型的数组,会把数组作为一个整体],可以是Integer等包装类。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ArraysTest01 {
    public static void main(String[] args) {
        // List ebsCodes = Arrays.asList("USERNAME","REAP","NLS");
        List ebsCodes = Arrays.asList(12, 22, 33);  //存储包装类Integer

        // 把数组转换为集合,数组不能是基本类型的数组
        String[] s = {"aa", "bb", "cc"};
        List strlist = Arrays.asList(s);

        //上述代码等价于(但是又存在不同之处):
        List ebsCodes = new ArrayList();
        ebsCodes.add("USERNAME");
        ebsCodes.add("REAP");
        ebsCodes.add("NLS");
    }
}

注意:

        (1)该方法不适用于基本数据类型(byte,short,int,long,float,double,boolean),可以是包装类。
        (2)该方法将数组与列表链接起来,当更新其中之一时,另一个自动更新。
        (3)不支持add和remove方法。
                最重要的一点就是,不支持add和remove,如果不需要改变长度可以使用Arrays.asList()。

        调用Arrays.asList()生产的List的add、remove方法时报java.lang.UnsupportedOperationException异常,这是由Arrays.asList() 返回的是Arrays的内部类ArrayList, 而不是java.util.ArrayList。

5.2.2 排序方法

        static void sort(参数数据 arr)     对指定类型数组按数字升序进行排序。 

        参数介绍:
                arr - 要搜索的数组(byte/short/int/long/float/double/char/Object)

        static void sort(参数数据 arr, int fromIndex, int toIndex)     对指定 byte 型数组的指定范围按数字升序进行排序。 

        参数介绍:
                arr - 要搜索的数组(byte/short/int/long/float/double/char/Object);
                fromIndex - 要排序的第一个元素的索引(包括);
                toIndex - 要排序的最后一个元素的索引(不包括);

import java.util.Arrays;

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

        //static void sort(int[] a) 对指定的 int 型数组按数字升序进行排序。 
        int arr[] = {31, 89, 9, 2, 77, 6, 100};

        Arrays.sort(arr); //对原数组进行排序

        //Arrays.toString(数组)  把数组的内容输出
        System.out.println(Arrays.toString(arr)); //已经升序排列 [2, 6, 9, 31, 77, 89, 100]

        /*
         * 在Arrays这个API里面,没有给我们提供降序排列的方法
         */
        /*
         * 反转数组
         * 七个值: 3次
         * 八个值: 4次
         *
         * 数组长度/2
         * 0	6
         * 1	5
         * 2	4
         *
         */
        //对数组进行逆序排列
        for (int i = 0; i < arr.length / 2; i++) {
            //先得定义一个临时变量来存储某个值
            int temp = arr[i];
            //把后面的赋值给前面的
            arr[i] = arr[arr.length - 1 - i];
            arr[arr.length - 1 - i] = temp;
        }

        System.out.println(Arrays.toString(arr)); //通过自己代码实现数组的逆序排列
    }
}

5.2.3 二分搜索法

        static int binarySearch(参数数组 arr, 对应数组的key)        使用二分搜索法来搜索指定类型数组,以获得指定的值。必须在进行此调用之前对数组进行排序(通过 sort(byte[]) 方法)。如果没有对数组进行排序,则结果是不确定的。如果数组包含多个带有指定值的元素,则无法保证找到的是哪一个。 

        参数介绍:
                arr - 要搜索的数组(byte/short/int/long/float/double/char/Object);
                key - 要搜索的值;

        返回值介绍:
                如果它包含在数组中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。插入点 被定义为将键插入数组的那一点:即第一个大于此键的元素索引,如果数组中的所有元素都小于指定的键,则为 a.length。注意,这保证了当且仅当此键被找到时,返回的值将 >= 0。

                static int binarySearch(参数数组 arr, int fromIndex, int toIndex, 对应数组的key)    使用二分搜索法来搜索指定类型数组的范围,以获得指定的值。 

        参数介绍:
                arr - 要搜索的数组(byte/short/int/long/float/double/char/Object);
                fromIndex - 要搜索的第一个元素的索引(包括);
                toIndex - 要搜索的最后一个元素的索引(不包括);
                key - 要搜索的值;

        返回值介绍:
                如果它包含在数组的指定范围内,则返回搜索键的索引;否则返回 (-(插入点) - 1)。插入点 被定义为将键插入数组的那一点:即范围中第一个大于此键的元素索引,如果范围中的所有元素都小于指定的键,则为 toIndex。注意,这保证了当且仅当此键被找到时,返回的值将 >= 0。 

public class ArraysTest03 {
    public static void main(String[] args) {
        int[] arr3 = new int[]{-98, -34, 2, 34, 54, 66, 79, 105, 210, 333};
        int index = Arrays.binarySearch(arr3, 210);
        if (index >= 0) {
            System.out.println(index);
        } else {
            System.out.println("未找到");
        }
    }
}

5.2.4 拷贝数组

        static 参数类型数组 copyOf(参数数组 arr, int newLength)     复制指定的数组,截取或用默认值填充(如有必要),以使副本具有指定的长度。 

        参数介绍:
                original - 要复制的数组(byte/short/int/long/float/double/char/Object/boolean);
                newLength - 要返回的副本的长度;

        返回:
                原数组的副本,截取或用默认值元素填充以获得指定的长度;
                默认值:
                        数值类型 - 0/0.0;
                        布尔类型 - false;
                        字符类型 - 空字符;
                        引用类型 - null;
        抛出: 
                NegativeArraySizeException - 如果 newLength 为负; 
                NullPointerException - 如果 original 为 null;

public class ArraysTest04 {
    public static void main(String[] args) {
        int[] arr1 = new int[]{1, 2, 3, 4};

        // 复制的长度超过原数组长度,默认值填充
        int[] newArr1 = Arrays.copyOf(arr1, 7);

        // 复制的长度不超过原数组长度,截取
        int[] newArr2 = Arrays.copyOf(arr1, 2);

        // 输出
        System.out.println(Arrays.toString(newArr1));
        System.out.println(Arrays.toString(newArr2));
    }
}

5.2.5 拷贝数组指定范围

        static 参数类型数组 copyOfRange(参数数组 arr, int from, int to)     将指定数组的指定范围复制到一个新数组。 

        参数介绍:
                original - 要复制的数组(byte/short/int/long/float/double/char/Object/boolean);
                from - 要复制的范围的初始索引(包括);
                to - 要复制的范围的最后索引(不包括)。(此索引可能位于数组范围之外)。 

        返回:
                包含取自原数组指定范围的新数组,截取或用默认值元素填充以获得所需长度;

        抛出: 
                ArrayIndexOutOfBoundsException - 如果 from < 0 或 from > original.length();
                IllegalArgumentException - 如果 from > to;
                NullPointerException - 如果 original 为 null;

5.2.6 数组转换字符串

        static String toString(参数数组 arr)     返回指定数组内容的字符串表示形式。 

        参数数组 arr: 任意数据类型的数组

        static String deepToString(参数数组 arr)     返回指定数组“深层内容”的字符串表示形式。 

        返回指定数组“深层内容”的字符串表示形式。如果数组包含作为元素的其他数组,则字符串表示形式包含其内容等。此方法是为了将多维数组转换为字符串而设计的。 

5.2.7 数组比较

        static boolean equals(参数数组 arr1,参数数组 arr2)     如果两个指定类型数组彼此相等,则返回 true。 

        参数介绍:
                arr1 - 将测试其相等性的一个数组;
                arr2 - 将测试其相等性的另一个数组; 

        如果两个指定的 boolean 型数组彼此相等,则返回 true。如果两个数组包含相同数量的元素,并且两个数组中的所有相应元素对都是相等的,则认为这两个数组是相等的。换句话说,如果两个数组以相同顺序包含相同的元素,则两个数组是相等的。此外,如果两个数组引用都为 null,则认为它们是相等的。

import java.util.Arrays;

public class ArraysTest05 {
    public static void main(String[] args) {
        // boolean equals(int[] a,int[] b):判断两个数组是否相等。
        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);
    }
}

5.2.8 数组填充

        static void fill(参数数组 arr1, 参数类型 val)     将指定类型的值分配给指定类型数组的每个元素。 

        参数:
                arr1 - 要填充的数组;
                val - 要存储在数组所有元素中的值;

        static void fill(参数数组 arr1, int fromIndex, int toIndex, 参数类型 val)    将指定类型的值分配给指定类型数组指定范围中的每个元素。 

        参数:
                arr1 - 要填充的数组;
                fromIndex - 要使用指定值填充的第一个元素的索引(包括);
                toIndex - 要使用指定值填充的最后一个元素的索引(不包括);
                val - 要存储在数组所有元素中的值;

        抛出: 
                IllegalArgumentException - 如果 fromIndex > toIndex;
                ArrayIndexOutOfBoundsException - 如果 fromIndex < 0 或 toIndex > a.length;

public class ArraysTest06 {
    public static void main(String[] args) {
        int[] arr1 = new int[]{1, 2, 3, 4};

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

    }
}

六、数组常见异常

        数组脚标越界异常(ArrayIndexOutOfBoundsException)。
                int[] arr = new int[2];
                System.out.println(arr[2]);
                System.out.println(arr[-1]);
                访问到了数组中的不存在的脚标时发生。

        空指针异常(NullPointerException)。
                int[] arr = null;
                System.out.println(arr[0]);
                arr引用没有指向实体,却在操作实体中的元素时。

七、课后练习题

7.1 程序题

1、某小区单间短期出租4个月,550元/月(水电煤公摊,网费35元/月),空调、卫生间、厨房齐全。屋内均是IT行业人士,喜欢安静。所以要求来租者最好是同行或者刚毕业的年轻人,爱干净、安静。电话如下代码:

public class ArrayTest {
    public static void main(String[] args) {
        int[] arr = new int[]{8, 2, 1, 0, 3};
        int[] index = new int[]{2, 0, 3, 2, 4, 0, 1, 3, 2, 3, 3};
        String tel = "";
        for (int i = 0; i < index.length; i++) {
            tel += arr[index[i]];
        }
        System.out.println("联系方式:" + tel); // 联系方式:18013820100
    }
}

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

        提示:先读入学生人数,根据人数创建int数组,存放学生成绩。

import java.util.Scanner;

public class ScoreTypes {
    public static void main(String[] args) {
        //1.使用Scanner,读取学生个数
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入学生人数:");
        int number = scanner.nextInt();

        //2.创建数组,存储学生成绩:动态初始化
        int[] scores = new int[number];
        //3.给数组中的元素赋值
        System.out.println("请输入" + number + "个学生成绩:");
        int maxScore = 0;
        for (int i = 0; i < scores.length; i++) {
            scores[i] = scanner.nextInt();
            //4.获取数组中的元素的最大值:最高分
            if (maxScore < scores[i]) {
                maxScore = scores[i];
            }
        }
        //		for(int i = 0;i < scores.length;i++){
        //			if(maxScore < scores[i]){
        //				maxScore = scores[i];
        //			}
        //		}

        //5.根据每个学生成绩与最高分的差值,得到每个学生的等级,并输出等级和成绩
        char level;
        for (int i = 0; i < scores.length; i++) {
            if (maxScore - scores[i] <= 10) {
                level = 'A';
            } else if (maxScore - scores[i] <= 20) {
                level = 'B';
            } else if (maxScore - scores[i] <= 30) {
                level = 'C';
            } else {
                level = 'D';
            }

            System.out.println("student " + i +
                    " score is " + scores[i] + ",grade is " + level);
        }
    }
}

3、获取arr数组中所有元素的和。
        提示:使用for的嵌套循环即可。

【Java基础系列教程】第五章 Java数组详解_第19张图片

public class ArraySum {

    public static void main(String[] args) {
        int[][] arr = new int[][]{{3, 5, 8}, {12, 9}, {7, 0, 6, 4}};
        // 记录总和
        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);
    }
}

4、回形数格式方阵的实现:
        从键盘输入一个整数(1~20),则以该数字为矩阵的大小,把1,2,3…n*n 的数字按照顺时针螺旋的形式填入其中。
        例如: 输入数字2,则程序输出:
            1 2 
            4 3
        输入数字3,则程序输出: 
            1 2 3 
            8 9 4 
            7 6 5
        输入数字4, 则程序输出:
            1  2  3  4 
            12 13 14 5 
            11 16 15 6 
            10 9  8  7

import java.util.Scanner;

class RectangleTest01 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入一个数字");
        int len = scanner.nextInt();
        int[][] arr = new int[len][len];

        int s = len * len;
        /*
         * k = 1:向右 k = 2:向下 k = 3:向左 k = 4:向上
         */
        int k = 1;
        int i = 0, j = 0;
        for (int m = 1; m <= s; m++) {
            if (k == 1) {
                if (j < len && arr[i][j] == 0) {
                    arr[i][j++] = m;
                } else {
                    k = 2;
                    i++;
                    j--;
                    m--;
                }
            } else if (k == 2) {
                if (i < len && arr[i][j] == 0) {
                    arr[i++][j] = m;
                } else {
                    k = 3;
                    i--;
                    j--;
                    m--;
                }
            } else if (k == 3) {
                if (j >= 0 && arr[i][j] == 0) {
                    arr[i][j--] = m;
                } else {
                    k = 4;
                    i--;
                    j++;
                    m--;
                }
            } else if (k == 4) {
                if (i >= 0 && arr[i][j] == 0) {
                    arr[i--][j] = m;
                } else {
                    k = 1;
                    i++;
                    j++;
                    m--;
                }
            }
        }

        // 遍历
        for (int m = 0; m < arr.length; m++) {
            for (int n = 0; n < arr[m].length; n++) {
                System.out.print(arr[m][n] + "\t");
            }
            System.out.println();
        }
    }
}
import java.util.Scanner;

class RectangleTest02 {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入一个数字");
        int n = scanner.nextInt();
        int[][] arr = new int[n][n];

        int count = 0; // 要显示的数据
        int maxX = n - 1; // x轴的最大下标
        int maxY = n - 1; // Y轴的最大下标
        int minX = 0; // x轴的最小下标
        int minY = 0; // Y轴的最小下标
        while (minX <= maxX) {
            for (int x = minX; x <= maxX; x++) {
                arr[minY][x] = ++count;
            }
            minY++;
            for (int y = minY; y <= maxY; y++) {
                arr[y][maxX] = ++count;
            }
            maxX--;
            for (int x = maxX; x >= minX; x--) {
                arr[maxY][x] = ++count;
            }
            maxY--;
            for (int y = maxY; y >= minY; y--) {
                arr[y][minX] = ++count;
            }
            minX++;
        }

        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length; j++) {
                String space = (arr[i][j] + "").length() == 1 ? "0" : "";
                System.out.print(space + arr[i][j] + " ");
            }
            System.out.println();
        }
    }
}

7.2 判断题

1、声明:int[] x,y[]; 在给x,y变量赋值以后,以下选项允许通过编译的是:
        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[][]

2、下面数组定义正确的有:
        A.String strs[] = {"a" "b" "c"};  
        B.String[] strs = {"a", "b", "c"};
        C.String[] strs = new String{"a" "b" "c"};
        D.String strs[] = new String[]{"a", "b", "c"};
        E.String[] strs = new String[3]{"a", "b", "c"};

        正确:B D

 3、分析程序,并写出执行结果

public class Test{
    public static void main(String[] args){
        int i,s= 0;
        int a[] = {10,20,30,40,50,60,70,80,90};

        for(i=0;iString arr[] = new String[]{"AA", "BB", "CC", "DD", "EE", "FF", "GG"};

System.out.println("反转之前:");
for (String str : arr) {
    System.out.print(str + "\t");
}
System.out.println("\n-------------------------------------------");
/*
 * 分析:
 *   长度7  奇数  7/2 = 3
 *   0   6
 *   1   5
 *   2   4
 *   长度6   偶数 6/2 = 3
 *
 * 交换的次数: 数组长度 / 2
 * */
/*for(int i = 0;i < arr.length / 2;i++){
    // 定义临时变量
    String temp = arr[i]; // 临时变量保存的是哪个,就先给哪个赋值
    arr[i] = arr[arr.length - 1 - i];
    arr[arr.length - 1 - i] = temp;
}*/

for(int i = 0,j = arr.length - 1;i < j;i++,j--){ // i = 3 j = 3
    // 定义临时变量
    String temp = arr[i]; // 临时变量保存的是哪个,就先给哪个赋值
    arr[i] = arr[j];
    arr[j] = temp;
}

System.out.println("反转之后:");
for (String str : arr) {
    System.out.print(str + "\t");
}

你可能感兴趣的:(Java基础系列教程,java,蓝桥杯,Java基础,JavaSE,数组)