【Java学习笔记(一百二十五)】之数组与Arrays工具类

本文章由公号【开发小鸽】发布!欢迎关注!!!


老规矩–妹妹镇楼:

一、数组概述

(一)概述

        数组,是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。 数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。

        创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址。数组的长度一旦确定,就不能修改,可以直接通过索引的方式调用指定位置的元素。

(二)数组分类

        维度:一维数组、二维数组、三维数组

        元素的数据类型:基本数据类型元素的数组、引用数据类型元素的数据


二、一维数组

(一)数组的声明

        一维数组的声明方式:type var[]或type[] var;

        如下所示:

//数组的声明,两种方式
int[] arr1;
int arr2[];

        注意,在声明数组时不能指定数组的长度,如int a[5]; 这种用法是非法的!

(二)数组的初始化

        一维数组的初始化分为动态初始化和静态初始化。

1.动态初始化

        所谓的动态初始化指的是将数组的声明和数组的赋值操作分开,这种情况下数组声明时必须指定数组的长度,长度不可变。如下所示:

//1.动态初始化:必须指定数组的长度,数组长度不可变
//基础数据类型各有各的默认值,引用数据类型默认为null
int[] arr3 = new int[2];
arr3[0] = 1;

2.静态初始化

        所谓的静态初始化指的是在定义数组的同时就为数组元素分配空间并赋值,如下所示:

//2.静态初始化:声明数组并赋值
int[] arr4 = new int[]{1,2,3};

3.数组元素的默认值

        数组一旦被分配了内存空间,其中的每个元素也会按照数组中的元素类型被隐式地初始化默认值,对于基本数据类型,根据每个数据类型默认值各有不同。对于引用数据类型,默认初始值为null。
在这里插入图片描述


(三)数组的内存

        Java中通过new来初始化数组,对于数组的内存状态变化从数组的声明开始。

        当声明一个数组后,就会在栈内存中入栈数组的首地址;

        当通过new初始化数组后,会在堆内存中分配数组的内存空间,若是动态初始化则会初始化默认值;

        当修改数组的元素时,直接在对内存中的数组内存空间中修改指定的元素值;


三、多维数组

        Java中支持多维数组,其实所谓的二维数组就是一维数组作为另一个一位数组的元素而存在。

(一)数组的初始化

1.动态初始化

        对于多维数组,动态初始化可以指定每个维度数组的长度,也可以只指定第一维数组的长度,目的是保证栈空间中的数组首地址能够找到后续堆空间中new出来的数组即可。如下所示:

//1.动态初始化多维数组:二维数组中有3个一维数组,每个一维数组中有2个元素
int[][] arrMul1 = new int[3][2];
arrMul1[0][0] = 1;

        可以看到的是,二维数组中有三个一维数组,每个一维数组中有两个元素。

//2.动态初始化:可以只指定第一维的数组长度,保证栈空间中的数组首地址能够找到即可
int[][] arrMul2 = new int[3][];
arrMul2[0] = new int[3];
arrMul2[1] = new int[]{1,2,3};

        可以看到的是,可以只指定第一维的数组长度,然后初始化一维数组。

2.静态初始化

        多维数组的静态初始化中,不需要指定数组的多维长度,直接赋值,如下所示:

//3.静态初始化:不需要指定数组的二维长度,同时可以看到的是多维数组的长度并非是规则的
int[][] arrMul3 = new int[][]{{1,2},{4,5,6}};
//也可以去掉int[][],直接进行赋值
int[][] arrMul4 = {{1,2,3},{4,5,6}};

        可以看到的是,Java中多维数组并不都是规则的矩阵形式,每个维度的数组中长度都不一定相等。

(二)多维数组的内存

        对于多维数组,首先数组名称arr变量存储的是堆空间中new出来的数组首地址,然后arr4[0]存储的是第一个一维数组所在的地址,接着arr4 [0] [0]才会存储着真正的数据元素。因此,二维数组是引用类型,一个一维数组引用着另一个一维数组,对于多维数组则是持续地引用下去。

        注意,对于未初始化的数组,是不能通过索引来获取元素的,这种情况下会产生空指针异常。

四、Arrays工具类

(一)Arrays.sort

        Arrays数组工具类中较为常用的排序方法,可以按照默认的排序方法排序,也可以自定义Comparator进行排序。

1.Arrays.sort(T[] a)

        对一个数组中的所有元素进行排序,排序规则为默认的递增排序,如下所示:

Integer[] intArr1 = new Integer[]{3,2,1};

//Arrays.sort
//1.普通的sort排序
Arrays.sort(intArr1);

2.Arrays.sort(T[] a, int fromIndex, int toIndex)

        仅仅对数组中的部分元素进行排序,范围为[fromIndex, toIndex),还是默认的递增规则。

//2.范围的sort排序
Arrays.sort(intArr1, 0, 2);

3.Arrays.sort(T[] a, Comparator<? super T> c)

        自定义Comparator的排序规则,可以实现与默认递增排序相反的递减排序,较为简洁的写法是new一个匿名内部类,并自定义compare规则。

        需要注意的是,基本数据类型的数组是无法使用Comparator进行比较排序的,要使用包装类数组进行排序,如int要转换为Integer进行排序。

        对于Comparator内部类,重写的compare规则中,返回int类型的值,若要实现递增规则的排序,则对于两个数o1和o2,较小的数排列在前,返回的就是较小的数-较大的数,即负值。这种规则比较容易混淆,因此需要牢记。如下所示:

//3.自定义Comparator排序规则
Arrays.sort(intArr1, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        //递增排序,o1 < o2,则return 负值
        return o1-o2;
    }
});

        在一些特殊场景中,比如LeetCode的刷题过程中,如果按照上述的写法则可能会遇到数值的溢出情况,如Integer.MIN_VALUE - Integer.MAX_VALUE,因此在考虑数值溢出情况下,应该用如下的写法:

//考虑数值溢出的写法
Arrays.sort(intArr1,new Comparator<Integer>(){
    public int compare(Integer o1,Integer o2){
        if(o1 > o2)return 1;
        else if(o1 < o2)return -1;
        else return 0;
    }
});

        也可以采用Lambda表达式的简洁写法:

//lambda表达式的简洁写法
Arrays.sort(intArr1, (p1, p2) -> p1 < p2 ? -1 : 1);

(二)Arrays.copyOf

        当想要将一个数组复制到一个新的数组中时,可以使用Arrays.copyOf方法进行复制,如下所示:

//        Arrays.copyOf(),复制数组为新的数组
        Integer[] intArr2 = Arrays.copyOf(intArr1, 5);
        System.out.println("copyOf得到的新的数组长度为:" + intArr2.length);

(三)Arrays.fill

        将指定的值填充到数组中的每个元素中,如下所示:

//填充指定值到数组的每个元素中,源码解析
Arrays.fill(intArr2, 3);

(四)Arrays.equals

        当需要判断两个数组是否相同、数组中各个元素是否相等时,可以使用Arrays.equals方法进行判断,如下所示:

//Arrays.equals(),判断两个数组是否相同,每个元素是否相等
boolean equals = Arrays.equals(intArr1, intArr2);
System.out.println("数组1和数组2是否相等:" + equals);

        该方法的源码如下所示,可以看到,由于数组是引用类型,首先判断的是引用对象的地址是否相等,即数组的首地址,其次判断数组的长度是否相同,最后分别判断两个数组的每个元素是否相同:

public static boolean equals(Object[] a, Object[] a2) {
    if (a==a2)
        return true;
    if (a==null || a2==null)
        return false;

    int length = a.length;
    if (a2.length != length)
        return false;

    for (int i=0; i<length; i++) {
        Object o1 = a[i];
        Object o2 = a2[i];
        if (!(o1==null ? o2==null : o1.equals(o2)))
            return false;
    }

    return true;
h;
    if (a2.length != length)
        return false;

    for (int i=0; i<length; i++) {
        Object o1 = a[i];
        Object o2 = a2[i];
        if (!(o1==null ? o2==null : o1.equals(o2)))
            return false;
    }

    return true;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值