Arrays工具类的使用(十七)上

一. Arrays 工具类


一.一 为什么出现 Arrays 工具类


在开发当中,虽然经常使用的是集合维护数据,但是数组的使用频率也是很高的,尤其是在 Java SE 阶段。


数组,常见的有 添加数据,删除数据,更新数据,搜索数据,排序, 获取长度,数组最大/小值 等很多内容。


在 JDK 1.2 版本时, 为了方便维护数组, 增加了一个 Arrays 的工具类。


Arrays 类 位于 java.utils 包下。


一.二 Arrays 工具类的常见方法


数组,有多种类型的数组, int,float,char,boolean 等, 所以Arrays 工具类中里面有很多的重载方法。 这里只以最常用的 int 类型进行举例。


Arrays工具类的使用(十七)上


Arrays工具类的使用(十七)上


Arrays工具类的使用(十七)上


二. Arrays 工具类的具体使用


二.一 转换成集合 asList(T … a)


二.一.一 例子


 @Test
    public void asListTest(){
        //转换成集合
        List<Integer> arrList=Arrays.asList(1,2,3,4,5,6,7,8,9);

        System.out.println("转换成后长度:"+arrList.size()+",内容是:"+arrList.toString());
    }


控制台打印输出:


Arrays工具类的使用(十七)上


二.一.二 简单内部实现


Arrays工具类的使用(十七)上


注意,内部构造的 ArrayList 并不是 java.util.ArrayList, 而是 Arrays 内部类 ArrayList.


二.二 打印内容 toString(int[] a)


二.二.一 例子


 @Test
public void toStringTest(){
    //数组
    int[] arr={1,2,3,4,5,6,7,8,9};
    //打印内容
    String str=Arrays.toString(arr);

    System.out.println("打印内容:"+str);
}


控制台打印输出:


Arrays工具类的使用(十七)上


二.二.二 简单内容实现


public static String toString(int[] a) {
        //为空时, 返回 null 
        if (a == null)
            return "null";
        //长度为0 时, 返回 [] 
        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            b.append(a[i]);
            if (i == iMax)
               {
                     return b.append(']').toString();
                }
            b.append(", ");
        }
    }
}


二.三 查询搜索 binarySearch(int[] a, int key)


二.三.一 无范围的例子


  @Test
    public void binarySearchTest1(){
        //数组
        int[] arr={1,2,3,4,5,6,7,8,9};
        int index=Arrays.binarySearch(arr,5);
        System.out.println("查询5的索引:"+index);
        index=Arrays.binarySearch(arr,10);
        System.out.println("查询10的索引:"+index);
    }


控制台打印输出:


Arrays工具类的使用(十七)上


内部实现,调用的是 有范围的查询, 查询的是 从0 到 arr.length 范围的


二.三.二 有范围的例子


    @Test
    public void binarySearchTest2(){
        //数组
        int[] arr={1,2,3,4,5,6,7,8,9};
        int index=Arrays.binarySearch(arr,4,8,5);
        System.out.println("查询5的索引:"+index);
        index=Arrays.binarySearch(arr,4,8,9);
        System.out.println("查询不在范围内的9的索引:"+index);
    }


控制台打印输出:


Arrays工具类的使用(十七)上


二.三.三 简单内部实现


 private static int binarySearch0(int[] a, int fromIndex, int toIndex,
                                     int key) {
        int low = fromIndex;
        //不包括 toIndex 索引处的位置
        int high = toIndex - 1;

        while (low <= high) {
            //获取中间位置, 二分查找
            int mid = (low + high) >>> 1;
            int midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        // 如果没有查找到, 返回的是 - (low+1), 并不一定是-1
        return -(low + 1);  // key not found.
    }


以 无范围的 10 例子进行举例, 传入过来的参数依次是: 1~9的数组,0,9,10.


那么 low=0, hight=8;


第一次循环: 0<=8, 成立。 mid=(0+8)/2=4, midVal=5, 5<10, 此时 low=4+1=5;


第二次循环: 5<=8, 成立, mid=(5+8)/2=6, midVal=7, 7<10, 此时 low=6+1=7;


第三次循环: 7<=8, 成立, mid=(7+8)/2=7, midVal=8, 8<10, 此时 low=7+1=8;


第四次循环: 8<=8, 成立, mid=(8+8)/2=8, midVal=9,9<10,此时 low=8+1=9;


9<=8, 不成立, 退出循环。 此时, low=9


返回 -(9+1)= -10, 最后结果返回 -10.


二.四 复制数组 copyOf 和范围复制数组 copyOfRange


二.四.一 copyOf 小例子


@Test
    public void copyOfTest(){
        //数组
        int[] arr={1,2,3,4,5,6,7,8,9};
        //只复制前5个
        int[] newArr=Arrays.copyOf(arr,5);

        System.out.println("newArr新数组长度:"+newArr.length+",内容:"+Arrays.toString(newArr));
    }


控制台打印输出:


Arrays工具类的使用(十七)上


内部调用的是 System 类的 arraycopy() 方法。


Arrays工具类的使用(十七)上


二.四.二 copyOfRange 小例子


 @Test
    public void copyOfRnageTest(){
        //数组
        int[] arr={1,2,3,4,5,6,7,8,9};
        //只复制 3~7 索引的位置。 不包括7 索引处的元素
        int[] newArr=Arrays.copyOfRange(arr,3,7);

        System.out.println("newArr新数组长度:"+newArr.length+",内容:"+Arrays.toString(newArr));
    }


控制台打印输出:


Arrays工具类的使用(十七)上


我们发现,内部调用的依然是 System 类的 arraycopy() 方法。


Arrays工具类的使用(十七)上


那么,接下来,我们就分析一下, System 类的 arraycopy() 方法 是如何实现数组复制的。


二.四.三 System 类的 arraycopy()


System 类位于 java.lang 包下, System 类用 final 进行修饰


  public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);


该方法 arraycopy 用 native 进行修饰,是用其他底层语言写的,可以快速进行数组复制。


这儿看不到具体的实现, 我们就仔细分析一下,各个参数吧。


src, 源数组。 即复制源是谁


srcPos, 从源数组的哪儿开始复制, 即复制的开始索引


dest ,目的数组, 即复制目的地是谁


destPos, 目的数组的源头在哪,即复制目的地的开始索引。 不一定是从0开始复制,支持中间索引位置处复制


length, 复制的长度。


这五个参数的顺序不能搞错。


copyOf() 方法时,传入过来的是 srcPos=0, destPos=0, length= Math.min(arr.length,newLength), 最小的那个长度。


表示从头开始复制。 如果newLength> arr.length 的话, 那么从 arr.length~newLength 处的值为默认值。


copyOfRange() 方法时,传入过来的是 srcPos=from, destPos=0,length=Math.min(arr.length-from, to-from)


二.四.四 System 类的 arraycopy() 方法举例


   @Test
    public void arraycopyTest(){
        //源数组
        int[] arr={1,2,3,4,5,6,7,8,9};
        //目标
        int [] dest={100,101,102,103,104,105,106,107,108,109,110};

        // 从103处开始复制, 拿过来的是 开始位置是5, 拿5个。
        System.arraycopy(arr,4,dest,3,5);

        // System.arraycopy(arr,4,dest,3,5);: 新复制的长度:11,内容:[100, 101, 102, 5, 6, 7, 8, 9, 108, 109, 110]

        //System.arraycopy(arr,4,dest,3,6); java.lang.ArrayIndexOutOfBoundsException
        System.out.println("新复制的长度:"+dest.length+",内容:"+Arrays.toString(dest));
    }


控制台打印输出:


Arrays工具类的使用(十七)上


需要注意,两个数组, 源数组 src, 目标数组 dest 的原始长度可能不一致, 复制的开始位置也可能不一致,而复制的长度是一致的, 而数组 dest的长度是无法改变的, 所以很有可能造成 ArrayIndexOutOfBoundsException 异常。


要保证: srcPos+length<= src.length; destPos+length<=dest.length;


上一篇:牛客网数据库SQL实战详细剖析(21-30)


下一篇:springboot + rabbitmq 做智能家居,我也没想到会这么简单