• javaSE - Arrays - 数组的定义与使用


    一、数组基本用法

    1.1、什么是数组

    数组本质上就是让我们能 “批量” 创建相同类型的变量
    也可以说是存储一组相同数据类型的数据的集合

    如:
    如果需要表示两个数据, 那么直接创建两个变量即可 int a; int b
    如果需要表示五个数据, 那么可以创建五个变量 int a1; int a2; int a3; int a4; int a5;
    但是如果需要表示一万个数据, 那么就不能创建一万个变量了. 这时候就需要使用数组, 帮我们批量创建

    注意事项: 在 Java 中, 数组中包含的变量必须是 相同类型

    1.2、创建数组

    基本语法
    创建数组的三种方式:

    // 动态初始化
    数据类型[] 数组名称 = new 数据类型 [] { 初始化数据 };
    // 静态初始化
    数据类型[] 数组名称 = { 初始化数据 };
    
    类型[] 数组名 = new 类型[元素个数];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    代码示例:

    public static void main(String[] args) {
            //动态初始化,数组里面存放了 1 2 3 4 
            int[] array2 = new int[]{1, 2, 3, 4};
            //静态初始化,数组里面存放了 1 2 3 4
            int[] array1 = {1, 2, 3, 4};
            //这里只是没有初始化数组的内容,默认里面存放的是5个0
            int[] array3 = new int[5];
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述
    而且对数组有一定了解的人,都知道数组的每个元素都有一个下标(从0开始),方便去寻找寻找元素.
    在这里插入图片描述

    1.3、总结

    一套讲解下来,你会发现在Java中 是这么来表达一个数组:int[] array
    其实数组也可以写成
    int arr[] = {1, 2, 3};
    和 C 语言一样. 但是我们还是更推荐写成 int[] arr 的形式. int和 [] 是一个整体.,因此,其实在Java中数组的写法更为准确。

    但是不能像C语言一样这样写 int array[10] = {0};
    我们前面也看到了,在创建一个数组时,[ ]里是不能有具体数字的存在,除了第三种方法,其它的,一律不行

    1.4、数组的使用

    1.4.1、代码示例: 获取长度 , 访问元素

    public static void main(String[] args) {
            int[] array = new int[]{1,2,3,4,5,6};
            //计算数组的长度
            int len = array.length;
            System.out.println("数组的长度为:" + len);
            //访问数组的元素
            System.out.println(array[1]);
            System.out.println(array[2]);
            System.out.println(array[3]);
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    1.4.2、代码示例: 下标越界

    public static void main(String[] args) {
            int[] array = new int[]{1,2,3,4,5,6};
            System.out.println(array[-1]);
        }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述
    抛出了 java.lang.ArrayIndexOutOfBoundsException 异常. 使用数组一定要下标谨防越界.

    1.4.3、码示例: 遍历数组

    所谓 “遍历” 是指将数组中的所有元素都访问一遍, 不重不漏. 通常需要搭配循环语句

    public static void main(String[] args) {
            int[] array = new int[]{1,2,3,4,5,6};
            for(int i = 0; i < array.length; i++){
                System.out.print(array[i] + " ");
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    1.1.4、代码示例: 使用 for-each 遍历数组

    public static void main(String[] args) {
            int[] array = {1, 2, 3, 4, 5};
            for(定义一个 与数组元素类型 相同的变量 : 数组名)
     
      什么意思呢?
    for-each(增强for循环), 数组名部分,表示的意思 遍历访问数组的元素
    将访问的元素赋给 冒号前面 定义的 与数组元素类型相同 的变量
     我们只需要 将该变量每次得到的元素值,打印
      就能做到不依靠元素下标,遍历打印数组所有元素
    
            for (int x: array) {
                System.out.print(x + " ");
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    那么 for 和 foreach 两者有什么区别?
    最大的区别在于,for是可以拿到元素下标,而foreach拿不到元素下标
    for循环用到的地方很多,但是foreach呢?
    当我们只需要元素的值时,就是使用foreach,
    当我们还需要元素的下标时,就用for。
    for-each 是 for 循环的另外一种使用方式. 能够更方便的完成对数组的遍历. 可以避免循环条件和更新语句写错

    注意事项

    1. 使用 arr.length 能够获取到数组的长度. . 这个操作为成员访问操作符. 后面在面向对象中会经常用到.
    2. 使用 [ ] 按下标取数组元素. 需要注意, 下标从 0 开始计数
    3. 使用 [ ] 操作既能读取数据, 也能修改数据.
    4. 下标访问操作不能超出有效范围 [0, length - 1] , 如果超出有效范围, 会出现下标越界异常

    代码实例3(借助Java的操作数组的工具类 Arrays)

    public static void main(String[] args) {
            int[] array = {1, 2, 3, 4, 5, 6};
            String str = Arrays.toString(array);
            System.out.println(str);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    Arrays工具类还有很多的方法:Arrays工具类的常用方法

    二、数组作为方法的参数

    首先要说一下 jvm内存模型

    public static void main(String[] args) {
            int[] array = {1, 2, 3, 4, 5, 6};
            String str = Arrays.toString(array);
            System.out.println(str);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    public static void main(String[] args) {
            int[] array = null;
            System.out.println(array.length);
        }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    2.1、基本用法

    2.1.1、代码示例: 打印数组内容

    /**
         * 打印数组的内容
         * @param array 数组名
         */
        public static void printf(int[] array){
            for (int i = 0; i < array.length; i++) {
                System.out.print(array[i] + " ");
            }
        }
        public static void main(String[] args) {
            int[] array = {1, 2, 3, 4, 5, 6};
            printf(array);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    2.2.2、通过下面题目更好的理解引用类型

    下面两题的输出结果是什么?
    题目1:

    public static void main(String[] args) {
            int[] array = {1,2,3,4,5};
            func1(array);
            System.out.println(Arrays.toString(array));// 图 18
    
        }
        public static void func1(int[] array){
            array = new int[]{11,2,13,4,51};
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    题目2:

    public static void main(String[] args) {
            int[] array = {1,2,3,4,5};
            func2(array);
            System.out.println(Arrays.toString(array));
        }
        public static void func2(int[] array){
            array[0] = 99;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    2.2.3、一个引用 是否 能同时 指向 多个对象?

    public static void main(String[] args) {
            int[] array1 = new int[]{1,2,3,4,5};
            array1 = new int[10];
            array1 = new int[2];
            array1 = new int[4];
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    答案是不能,如果前面认真看了,就该知道此时的array1,存储的地址,已经被改变(array是一个局部变量,意味着存的值是可以被改变的),现在存的是 new int[4] 的这个对象的地址, 而不是说,存几个对象的地址。

    一个引用只能指向一个对象(一个引用只能保存一个对象的地址)

    2.2.4、引用 就一定在栈上吗?

    答案是不一定的,因为一个变量在不在栈上,是你变量的性质决定的
    如果你的引用是一个局部变量,那就一定在栈上 实例成员变量那就不一定了。(先告诉你们有这个概念,等后面讲到成员变量时再说)

    局部变量的引用保存在栈上, new 出的对象保存在堆上.

    堆的空间非常大, 栈的空间比较小.    因为 堆 是整个 JVM 共享一个,
    而 栈 每个线程具有一份 (一个 Java 程序中可能存在多个栈)
    
    • 1
    • 2

    三、数组作为方法的返回值

    3.1、代码示例: 写一个方法, 将数组中的每个元素都 * 2(直接修改原数组)

    public static void main(String[] args) {
            //代码示例: 写一个方法, 将数组中的每个元素都 * 2
            // 直接修改原数组
            int[] array = {1,2,3,4,5};
            mul2(array);
            System.out.println(Arrays.toString(array));
        }
        public static void mul2(int[] array){
            for(int i = 0; i < array.length; i++){
                array[i] = array[i] * 2;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    这个代码固然可行, 但是破坏了原有数组. 有时候我们不希望破坏原数组, 就需要在方法内部创建一个新的数组, 并由方法返回出来

    3.2、代码示例: 写一个方法, 将数组中的每个元素都 * 2(将原数组拷贝一份,改变拷贝的数组,并返回拷贝的数组)

    public static void main(String[] args) {
            //代码示例: 写一个方法, 将数组中的每个元素都 * 2
            // 直接修改原数组
            int[] array = {1,2,3,4,5};
            int[] ret = mul2(array);
            System.out.println("原来的数组:" + Arrays.toString(array));
            System.out.println("改变后的数组:" + Arrays.toString(ret));
        }
    
        public static int[] mul2(int[] array){
            int[] str = new int[array.length];
            for(int i = 0; i < array.length; i++){
                str[i] = array[i] * 2;
            }
            return str;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述
    这样的话就不会破坏原有数组了.
    另外由于数组是引用类型, 返回的时候只是将这个数组的首地址返回给函数调用者, 没有拷贝数组内容, 从而比较高效

    四、数组练习

    4.1、模拟实现 ToString方法 ,数组转字符串

    这是java自带的ToString方法

    在这里插入图片描述
    模拟实现:

    public static void main(String[] args) {
            int[] array = {1,2,3,4,5};
            System.out.println(mytoString(array));
            //System.out.println(Arrays.toString(array));
        }
        public static String mytoString(int[] array){
            String str = "[";
            if(array.length == 0){
                return "[]";
            }
            for(int i = 0; i < array.length; i++){
                str = str + array[i];
                if(i != array.length - 1){
                    str = str + ",";
                }
            }
            str = str + "]";
            return str;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    4.2、数组拷贝 代码示例 拷贝整个数组

    拷贝整个数组

    public static void main(String[] args) {
            int[] array = {1,2,3,4,5};
            int[] str = Arrays.copyOf(array, array.length);
            System.out.println(Arrays.toString(str));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    模拟实现mycopyDf

    public static void main(String[] args) {
            int[] array = {1,2,3,4,5};
            int[] str = mycopyDf(array, array.length);
            //int[] str = Arrays.copyOf(array, array.length);
            System.out.println(Arrays.toString(str));
        }
    
        public static int[] mycopyDf(int[] array, int len){
            int[] str = new int[len];
            for (int i = 0; i < len; i++){
                str[i] = array[i];
            }
            return str;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4.3、数组拷贝 代码示例 拷贝某个范围

    拷贝某个范围

    public static void main(String[] args) {
            int[] array = {1,2,3,4,5};
            int[] str = Arrays.copyOfRange(array, 2, 4);
            System.out.println(Arrays.toString(str));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    4.4、找数组中的最大元素

    给定一个整型数组, 找到其中的最大元素 (找最小元素同理)

    public static void main(String[] args) {
            //找数组中的最大元素
            int[] array = {3,5,1,40,55,20,80};
            int max = printMax(array);
            System.out.println(max);
        }
    
        public static int printMax(int[] array){
            int max = array[0];
            for(int i = 0; i < array.length - 1; i++){
                if(max > array[i+1]){
                    max = array[i];
                }else {
                    max = array[i + 1];
                }
            }
            return max;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    类似于 “打擂台” 这样的过程. 其中 max 变量作为 擂台, 比擂台上的元素大, 就替换上去, 否则就下一个对手

    4.5、求数组中元素的平均值

    public static void main(String[] args) {
            //求数组中元素的平均值
            int[] array = {3,5,1,40,55,20,80};
            double scr = avgSum(array);
            System.out.println(scr);
        }
    
        public static double avgSum(int[] array){
            double sum = 0.0;
            for(int i = 0; i < array.length; i++){
                sum = sum + array[i];
            }
            return sum / array.length;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4.6、查找数组中指定元素(顺序查找)

    给定一个数组, 再给定一个元素, 找出该元素在数组中的位置

    public static void main(String[] args) {
            //查找数组中指定元素(顺序查找)
            //返回下标,没有返回-1
            int[] array = {3,5,1,40,55,20,80};
            int k = 1;
            int ret = func(k,array);
            System.out.println("下标为:" + ret);
        }
    
        public  static int func(int k , int[] array){
            for(int i = 0; i < array.length; i++){
                if(k == array[i]){
                    return i;
                }
            }
            return -1;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    4.7、 查找数组中指定元素(二分查找)

    针对有序数组, 可以使用更高效的二分查找.
    啥叫有序数组?
    有序分为 “升序” 和 “降序”
    如 1 2 3 4 , 依次递增即为升序.
    如 4 3 2 1 , 依次递减即为降序.
    以升序数组为例, 二分查找的思路是先取中间位置的元素, 看要找的值比中间元素大还是小. 如果小, 就去左边找; 否则就去右边找.

    public static void main(String[] args) {
            //二分查找
            int[] array = {1,2,3,4,5,6,7,8,9,10};
            //k 为要查找的数,找到返下标,找不到返回-1
            int k = 11;
            int ret = func(k,array);
            System.out.println(ret);
        }
    
        public static int func(int k, int[] array){
            int left = 0;
            int right = array.length - 1;
            while(left <= right){
                int mid = (left + right) / 2;
                if(array[mid] > k){
                    //中间值 > k,说明 k 是在中间值的左边
                    //此时的右值应该是中间值
                    right = mid - 1;
                }else if(array[mid] < k){
                    //中间值 < k,说明 k 是在中间值的右边
                    //此时的左值应该是中间值
                    left = mid + 1;
                }else{
                    return mid;
                }
            }
            return -1;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    4.8、检查数组的有序性

    给定一个整型数组, 判断是否该数组是有序的(升序)

    public static void main(String[] args) {
            //给定一个整型数组, 判断是否该数组是有序的(升序)
            int[] array = {1,2,3,4,10,6,7,8,9,10};
            boolean b = funcSce(array);
            System.out.println(b);
        }
    
        public static boolean funcSce(int[] array){
            for(int i = 0; i < array.length - 1; i++){
                if(array[i] > array[i+1]){
                    return false;
                }
            }
            return true;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    4.9、数组排序(冒泡排序)

    public static void main(String[] args) {
            //数组排序(冒泡排序)
            int[] array = {10,9,8,7,4,5,6,2,3,1};
            int[] ret = funcMao(array);
            System.out.println(Arrays.toString(ret));
        }
    
        public static int[] funcMao(int[] array){
            //i 表示比较多少对
            for(int i = 0; i < array.length-1; i++){
                //j 表示比较的趟数
                for(int j = 0; j < array.length - 1 - i ; j++){
                    if(array[j] > array[j+1]){
                        int tmp = array[j];
                        array[j] = array[j+1];
                        array[j+1] = tmp;
                    }
                }
            }
            return array;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    4.10、数组逆序

    给定一个数组, 将里面的元素逆序排列.
    思路
    设定两个下标, 分别指向第一个元素和最后一个元素. 交换两个位置的元素.
    然后让前一个下标自增, 后一个下标自减, 循环继续即可.

    public static void main(String[] args) {
            //数组逆序
            int[] array = {1,2,3,4,10,6,7,8,9,10};
            int[] ret = funcNixu(array);
            System.out.println(Arrays.toString(ret));
        }
    
        public static int[] funcNixu(int[] array){
            int left = 0;
            int right = array.length - 1;
            while(left <= right){
                int tmp = array[left];
                array[left] = array[right];
                array[right] = tmp;
                left++;
                right--;
            }
            return array;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    4.11、数组数字排列

    给定一个整型数组, 将所有的偶数放在前半部分, 将所有的奇数放在数组后半部分
    例如 {1, 2, 3, 4}
    调整后得到 {4, 2, 3,1}

    基本思路
    设定两个下标分别指向第一个元素和最后一个元素.
    用前一个下标从左往右找到第一个奇数, 用后一个下标从右往左找到第一个偶数, 然后交换两个位置的元素.依次循环即可.

    public static void main(String[] args) {
            //给定一个整型数组, 将所有的偶数放在前半部分, 将所有的奇数放在数组后半部分
            int[] array = {1,2,3,4,10,6,7,8,9,10};
            int[] ret = swapNum(array);
            System.out.println(Arrays.toString(ret));
        }
    
        public static int[] swapNum(int[] array){
            int left = 0;
            int right = array.length - 1;
            while(left <= right){
                if(array[left] % 2 == 0){
                    left++;
                }else if(array[right] % 2 != 0){
                    right--;
                }else {
                    int tmp = array[left];
                    array[left] = array[right];
                    array[right] = tmp;
                }
            }
            return array;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    五、 二维数组

    二维数组本质上也就是一维数组, 只不过每个元素又是一个一维数组

    5.1、基本语法

    二维数组的创建

    基本语法1

    	数据类型[][] 数组名 = { 初始化数据 }
    
    • 1

    基本语法2

    	 数据类型[][] 数组名 = new 数据类型[][]{ 初始化数据 }
    
    • 1

    基本语法3

    	数据类型[][] 数组名 = new 数据类型[行数][列数]
    
    • 1
    public static void main(String[] args) {
            //和一位数组一样的定义方式
            //直接初始化数据内容
            int[][] array1 = {{1,2,3},{4,5,6}};
            //动态初始化
            int[][] array2 = new int[][]{{1,2,3},{4,5,6}};
            //静态初始化,没有初始化内容,默认为0
            int[][] array3 = new int[2][3];
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5.2、二维数组的打印

    for循环打印

    public static void main(String[] args) {
            int[][] array1 = {{1,2,3},{4,5,6}};
            for (int i = 0; i < array1.length; i++) {
                for (int j = 0; j < array1[i].length; j++) {
                    System.out.print(array1[i][j] + " ");
                }
                System.out.println();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    for - each 打印数组

    public static void main(String[] args) {
            int[][] array1 = {{1,2,3},{4,5,6}};
            for (int[] str : array1) {
                for (int n: str) {
                    System.out.print(n + " ");
                }
                System.out.println();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    使用java自带的函数来打印二维数组(deepToString)

    在前面,我们使用了 Arrays.toString,将数组转换的字符串输出

    二维数组也有对应的 方法: Arrays.deepToString(数组名)

    public static void main(String[] args) {
            int[][] array1 = {{1,2,3},{4,5,6}};
    
            System.out.println(Arrays.deepToString(array1));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    5.3、一种特别的二维数组(不规则的二维数组)

    第一种情况:

    public static void main(String[] args) {
            int[][] array = {{1,2,},{4,5,6}};
            for (int i = 0; i < array.length; i++) {
                for (int j = 0; j < array[i].length; j++) {
                    System.out.print(array[i][j] + " ");
                }
                System.out.println();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    第二种情况:不规则二维数组
    二维数组可以省略列,不能省略行

    public static void main(String[] args) {
            int[][] array = new int[2][];
            //手动给 二维数组 赋值
            //第一行有3个元素
            array[0] = new int[3];
            //第二行有4个元素
            array[1] = new int[4];
            for (int i = 0; i < array.length; i++) {
                for (int j = 0; j < array[i].length; j++) {
                    System.out.print(array[i][j] + " ");
                }
                System.out.println();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

  • 相关阅读:
    系统架构设计师学习笔记——企业信息化战略与实施
    Java.lang.Class类 getDeclaredConstructors()方法有什么功能呢?
    HashMap -- 调研
    Nginx、LVS、Keepalived的关系
    MATLAB中uiwait函数用法
    二进制数据传输几个关键项记录——大小端、BCD码、CRC16校验
    TrOCR – 基于 Transformer 的 OCR 入门
    【excel】常用的50个函数与基础操作(逻辑函数)
    深入浅出,带你看懂Vue组件间通信的8种方案
    tf.GPUOptions
  • 原文地址:https://blog.csdn.net/ryy1999/article/details/128078646