Arrays工具类的常见方法总结

      JAVA开发工具包—JDK 中为我们提供了一个专门用于操作数组的工具类,即Arrays类,位于java.until包中。该类中的方法均为static修饰的静态方法,可以直接通过Arrays.xxx(xxx)的形式调用方法。主要提供了数组元素的复制、填充、比较、排序、查询等。Arrays工具类大多数是对数组进行的简化操作,ArrayList的底层也是基于数组实现的。

1.数组复制与创建

Arrays.copyOf( )

作用

        基于复制原数组的基础上创建一个新的数组,可指定长度(从头开始计算长度)。

        创建一个新的数组,该数组是原始数组的副本,并且可能具有不同的长度。

        使用方法 :先定义一个新数组,在通过Arrays.copyOf将原数组所需要的内容复制到新数组上(可指定长度,从头复制)eg: String[]  新数组名  =  Arrays.copyOf(原数组名  新数组长度);

      见下图,Arrays.copyOf 共有10中重载方法,其对应的参数类型不同,即数组类型不同,包含了基本类型和任意(自定义)引用类型,最终的实现都是一个核心的方法System.arraycopy,这是一个native方法,不需要深究。

参数        

        T[] original:要复制的原始数组(T[]:数组类型 original:原数组名)。

        int newLength,新数组的长度

返回值

        返回值为数组,即根据你指定长度复制的数组

举例

        String[]  新数组名  =  Arrays.copyOf(原数组名  新数组长度);

             “String[]  新数组名”用于存放复制的数组(返回值)

             “ Arrays.copyOf(原数组名  新数组长度)”调用方法

import java.util.Arrays;

public class demo01 {
	public static void main(String[] args) {
		//原数组
		String[] n1 = {"1","2","3"};
		//调用方法
		String[] n2 = Arrays.copyOf(n1,2);
		//输出原数组
		System.out.println(Arrays.toString(n1));
		//输出新数组
		System.out.println(Arrays.toString(n2));
		
	}
}

运行结果:

注:若定长度超出原数组长度,则多出元素为默认值

源代码解读

        他的各种类型都是雷同的,我们看一个int类型的。

        1.根据用户指定的新数组长度创建了一个数组copy,用来存储我们将复制的数据。

        2.调用System.arraycopy(原数组 起始下标,新数组,起始下标,要复制的元素数量)方法将原数组内容复制到新数组里。

        其中“original,0”指定原数组和从该数组的索引0开始复制,“copy,0”指定目标数组copy和从该数组的索引0开始写入数据),math.min(original.length,newLength)计算要复制的元素数量。如果新长度大于原始数组长度,只复制前newLength个元素,如果新长度大于原始数组的长度,则剩余部分用0填充。

        3.返回数组copy

/**
     * Copies the specified array, truncating or padding with zeros (if necessary)
     * so the copy has the specified length.  For all indices that are
     * valid in both the original array and the copy, the two arrays will
     * contain identical values.  For any indices that are valid in the
     * copy but not the original, the copy will contain <tt>0</tt>.
     * Such indices will exist if and only if the specified length
     * is greater than that of the original array.
     *
     * @param original the array to be copied
     * @param newLength the length of the copy to be returned
     * @return a copy of the original array, truncated or padded with zeros
     *     to obtain the specified length
     * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
     * @throws NullPointerException if <tt>original</tt> is null
     * @since 1.6
     */
    public static int[] copyOf(int[] original, int newLength) {
        int[] copy = new int[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

Arrays.copyOfRange( )

作用

        根据指定范围将原数组内容复制到新数组中,原数组内容不会被修改。是copyOf的升级版,是带范围的复制数组,相对与copyOf多了一个参数。

        复制数组,也可以说是变相的截取数组,因为数组在创建时就定义好长度,只能通过复制操作达到截取的目的,这个方法虽然更加灵活,但需要注意的也不少,源码中只是判断了from不能大于to,但没有排除下标为负数,下标为负数就会报错,且这种错误是native代码中报的,不好捕捉,尽量在执行前先进行参数的校验。

        Arrays.copyOfRange( )也有10种重载方法

参数

        T[] original:原始数组

         int from:开始复制的起始下标(包含)

         int to:停止复制的结束下标(不包含) 

        注:数组下标从0开始

返回值

         返回值为数组,即根据用户指定范围复制的数组,新数组的长度为to-from。

举例

        String[]  新数组名  =  Arrays.copyOfRange(原数组名,复制起始下标,复制截止下标);

              “String[]  新数组名”用于存放复制的数组(返回值)

              “ Arrays.copyOfRange(原数组名,复制起始下标,复制截止下标)”调用方法

import java.util.Arrays;

public class demo01 {
	public static void main(String[] args) {
		//原数组
		int[] n1 = {1,2,3};
		//调用方法
		int[] n2 = Arrays.copyOfRange(n1, 2, 5);
		//输出原数组
        //下标超出原数组,自动填充默认值0
		System.out.println(Arrays.toString(n1));
		//输出新数组
		System.out.println(Arrays.toString(n2));
	}
}

运行结果:

import java.util.Arrays;

public class demo01 {
	public static void main(String[] args) {
		//原数组
		int[] n1 = {1,2,3,4,5};
		//调用方法
		//下标不超出原数组
		int[] n2 = Arrays.copyOfRange(n1, 2,4);
		//输出原数组
		System.out.println(Arrays.toString(n1));
		//输出新数组
		System.out.println(Arrays.toString(n2));
	}
}

运行结果:

源代码解读

        1.计算新数组长度。 to和from下标之间的元素数量,如果新长度小于0,不符合使用规则,抛出 from 大于 to 的异常提醒。

        2..根据计算出的长度创建了一个数组copy,用来存储我们将复制的数据。

        3.调用System.arraycopy(原数组 起始下标,新数组,起始下标,要复制的元素数量)方法将原数组内容复制到新数组里。

        其中“original,0”指定原数组和从该数组的索引0开始复制,“copy,0”指定目标数组copy和从该数组的索引0开始写入数据),math.min(original.length,newLength)计算要复制的元素数量。如果新长度大于原始数组长度,只复制前newLength个元素,如果新长度大于原始数组的长度,则剩余部分用0填充。

        4.返回数组copy


    public static int[] copyOfRange(int[] original, int from, int to) {
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        int[] copy = new int[newLength];
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

Arrays.fill( )

作用

  初始化数组元素为指定值,即整个数组将会是同一个元素,可以指定区间进行填充,通过fromIndex和endIndex参数。可以用来快速设置数组中的元素为同一个值。

         Arrays.fill()主要分为两种重载方法(不指定范围or指定范围)

参数

        Arrays.fill()方法被重载,有两种不同的参数

         (1)T[] a:要填充的数组          

              T val:要填充的值

         (2)T[] a:要填充的数组

              int fromIndex:开始填充的起始下标(包含)

              int toIndex:停止填充的终止下标(不包含)

               int val:要填充的值

返回值

        没有返回值,作用是直接修改传入的数组

举例

1、不指定范围

import java.util.Arrays;

public class demo01 {
	public static void main(String[] args) {
		//原数组
		int[] n1 = {1,2,3,4,5};
		//调用方法
		//不指定范围赋值
		Arrays.fill(n1,7);
		//输出数组
		System.out.println(Arrays.toString(n1));
	}
}

运行结果:

2、指定范围

import java.util.Arrays;

public class demo01 {
	public static void main(String[] args) {
		//原数组
		int[] n1 = {1,2,3,4,5};
		//调用方法
		//指定范围赋值
		Arrays.fill(n1,2,4,7);
		//输出数组
		System.out.println(Arrays.toString(n1));
	}
}

运行结果:

源代码解读

1、不指定范围(其余类型皆雷同)

        通过for循环给数组挨个赋值         int[] a:要填充的数组         int val:要填充的值

 public static void fill(int[] a, int val) {
        for (int i = 0, len = a.length; i < len; i++)
            a[i] = val;
    }

2、 指定范围(其余类型皆雷同)

        T[] a:要填充的数组                                           int fromIndex:开始填充的起始下标(包含)

        int toIndex:停止填充的终止下标(不包含)     int val:要填充的值

        1.调用rangeCheck的私有方法,检查fromIndex和toIndex是否在数组a的有效范围内,如果不在有效范围内,则抛出异常

        2.通过for循环,从fromIndex开始,递增到toIndex之前的位置,每次迭代都将数组中下标为i的元素赋值为val

    private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
        if (fromIndex > toIndex) {
            throw new IllegalArgumentException(
                    "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
        }
        if (fromIndex < 0) {
            throw new ArrayIndexOutOfBoundsException(fromIndex);
        }
        if (toIndex > arrayLength) {
            throw new ArrayIndexOutOfBoundsException(toIndex);
        }
    }
  public static void fill(int[] a, int fromIndex, int toIndex, int val) {
        rangeCheck(a.length, fromIndex, toIndex);
        for (int i = fromIndex; i < toIndex; i++)
            a[i] = val;
    }

2.数组转集合

Arrays.asList( )

作用

        将一个数组转换为一个固定大小的List列表。

        这是开发中常用的初始化数组手段,比给List中一个一个add元素更快捷,不过此方法返回的List是java.util.Arrays.ArrayList类型,不支持增加、删除元素,但是可以修改和查看,一般用于初始化一个静态集合,只是用于读取和查看,相当于常量。

参数

        asList(T... a) ,是一个可变参数可以传递任意数量的对象作为参数,这些对象将被视为一个数组的元素。

返回值

        List<T>,返回一个固定大小的List,包含了传递给Arrays.asList()的所有元素。不能添加或删除元素。

举例
import java.util.Arrays;
import java.util.List;

public class demo01 {
	public static void main(String[] args) {
		//原数组
		Integer[] n1 = {1,2,3,4,5};
		//调用方法
		//数组-->集合
		//此方法不支持基础类型  只支持引用类型
		List<Integer> n2 = Arrays.asList(n1);
		//输出集合
		System.out.println(n2);
	}
}

输出结果:

将这一数组转换为List集合后,对应的列表是不支持添加和删除操作的,否则会报错

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

public class demo01 {
	public static void main(String[] args) {
		//原数组
		Integer[] n1 = {1,2,3,4,5};
		//调用方法
		//数组-->集合
		//此方法不支持基础类型  只支持引用类型
		List<Integer> n2 = Arrays.asList(n1);
		//输出集合
		System.out.println(n2);
		//添加一个元素5
		n2.add(5);
	}
}

输出结果:

转变为集合后,对集合进行修改,数组的元素也会修改

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


public class demo01 {
	public static void main(String[] args) {
		//原数组
		Integer[] n1 = {1,2,3,4,5};
		//调用方法
		//数组-->集合
		//此方法不支持基础类型  只支持引用类型
		List<Integer> n2 = Arrays.asList(n1);
		//输出数组
		System.out.println(n2);
		//添加一个元素5
		n2.set(2, 4);
		//输出集合
		System.out.println(n2);
		//输出数组
		System.out.println(Arrays.toString(n1));
	}
}

运行结果:

源代码解读

这个方法接受一个泛型参数 T,可以处理任何类型的对象,只要调用时提供一致的类型即可,必须是一个引用类型,不能是一个基本类型。

    @SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

Arrays.asList() 返回的 List 是一个 Arrays 类的内部类,它持有一个对原始数组的引用。这意味着对 List 的修改会反映到数组上。

3.数组排序

Arrays.sort( )

作用

        对数组进行升序排序(快速排序)。

参数

        Arrays.sort()方法被重载,主要分为两种

        1.无范围排序:   Object[] a  :要排序的数组

        2.范围排序:       Object[] a  :要排序的数组    

                                    int fromIndex:起始下标       int toIndex:截止下标

返回值

没有返回值,直接修改传入的数组,将其排序。

举例
import java.util.Arrays;

public class xx {
	public static void main(String[] args) {
		
		Integer[] n1 = {5,7,9,1,5,4,8,6,3,2};
		//输出排序前数组
		System.out.println(Arrays.toString(n1));
		//无范围排序
		Arrays.sort(n1);
		//输出排序后数组
		System.out.println(Arrays.toString(n1));

		System.out.println();
		
		Integer[] n2 = {5,7,9,1,5,4,8,6,3,2};
		//输出排序前数组
		System.out.println(Arrays.toString(n2));
		//范围排序
		Arrays.sort(n2, 3, 7);
		//输出排序后数组
		System.out.println(Arrays.toString(n2));
	}
	
}

运行结果: 

源代码解读

        对对象数组进行排序。它接受两个参数:一个对象数组 a和一个 Comparator 对象 c。Comparator 用于定义数组中元素的排序顺序。r如果Comparator对象c不是null,则进入else代码块,检查LegacyMergeSort.userRequested的静态变量,这个变量可能是一个标志,指示是否应该使用传统的归并排序算法,如果LegacyMergeSort.userRequested为true,则调用legacyMergeSort(a,c)方法对数组a使用归并排序算法进行排序,并使用提供的Comparator c.如果为false,则调用Time.sort(a,0,a.length,c,null,0,0)方法对数组a使用TimeSort算法进行排序。

    public static void sort(Object[] a) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a);
        else
            ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
    }
    public static void sort(Object[] a, int fromIndex, int toIndex) {
        rangeCheck(a.length, fromIndex, toIndex);
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a, fromIndex, toIndex);
        else
            ComparableTimSort.sort(a, fromIndex, toIndex, null, 0, 0);
    }

 

4.数组查询

Arrays.binarySearch( )

作用

        在排好序的数组中查找指定元素,并返回下标。如果找到该元素,则返回其下标(从0 开始),如果未找到该元素,则返回负值。

参数

        Arrays.binarySearch()方法被重载,主要有两种不同的参数

   (1)、binarySearch(T[] a,T key):

                        T[] a:已排序的数组           T key): 目标查找元素

   (2)、binarySearch(T[] a,int fromIndex,int toIndex,T key):

                         T[] a:已排序的数组           T key: 目标查找元素 

                         int fromIndex:从此下标开始查找(包括)

                         int toIndex:到此下标停止查找(不包括)

返回值

        如果找到目标元素,则返回该元素在数组中的下标(从0开始),如果没找到,则返回负值。

举例

1、无范围查找元素

import java.util.Arrays;

public class demo01 {
	public static void main(String[] args) {
		Integer[] n1 = {5,7,9,1,4,8,6,3,2};
		//排序
		Arrays.sort(n1);
		//输出数组
		System.out.println(Arrays.toString(n1));
		//查找
		int index = Arrays.binarySearch(n1, 5);
		//输出下标
		System.out.println(index);
	}
}

运行结果:

2、指定范围查找元素

import java.util.Arrays;

public class demo01 {
	public static void main(String[] args) {
		Integer[] n1 = {5,7,9,1,5,4,8,6,3,2};
		//排序
		Arrays.sort(n1);
		//输出数组
		System.out.println(Arrays.toString(n1));
		//查找
		int index = Arrays.binarySearch(n1,4,8,5);
		//输出下标
		System.out.println(index);
	}
}

 运行结果:

注:如数组中由相同元素,则返回最后一个目标元素的下标

源代码解读

        调用binarySearch0()的私有方法,执行二分搜索逻辑,根据传入的起始和结束下标(无范围查找调用binarySearch0()时自动传入0,数组长度), 以及要查找的键,来在数组中搜素元素并返回目标值的下标。

          二分查找:当一个数组经过排序后,先寻找中间的数据进行比较,当即排除一半数据,依此类推,减少寻址次数,相当于指数倍缩减。

无范围查找

         binarySearch0( )方法实现思路:low为低位0,high为高位数组a.length-1,然后通过计算得到中间位置mid,获取中间值midVal,然后再用中间值midVal和目标值key相较。
        若中间值midVal大于目标值key时,说明目标元素可能在目标数组的上半区,将high=mid-1,然后继续计算中间值,依次循环,直到low<=high时,循环结束。若找到目标元素,则返回其下标,若没找到,则返回一个负数 -(low + 1)
        若中间值midVal小于目标值key时,说明目标元素可能在目标数组的下半区,将low=mid+1,然后继续计算中间值,依次循环,直到low<=high时,循环结束。若找到目标元素,则返回其下标,若没找到,则返回一个负数 -(low + 1)

    public static int binarySearch(Object[] a, Object key) {
        return binarySearch0(a, 0, a.length, key);
    }

指定范围查找

    public static int binarySearch(Object[] a, int fromIndex, int toIndex,
                                   Object key) {
        rangeCheck(a.length, fromIndex, toIndex);
        return binarySearch0(a, fromIndex, toIndex, key);
    }

 引用

    // Like public version, but without range checks.
    private static int binarySearch0(Object[] a, int fromIndex, int toIndex,
                                     Object key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            @SuppressWarnings("rawtypes")
            Comparable midVal = (Comparable)a[mid];
            @SuppressWarnings("unchecked")
            int cmp = midVal.compareTo(key);

            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }
    private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
        if (fromIndex > toIndex) {
            throw new IllegalArgumentException(
                    "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
        }
        if (fromIndex < 0) {
            throw new ArrayIndexOutOfBoundsException(fromIndex);
        }
        if (toIndex > arrayLength) {
            throw new ArrayIndexOutOfBoundsException(toIndex);
        }
    }

5.数组打印 

Arrays.toString( )

作用

        将数组(无论是基本类型数组还是对象数组)的内容转换为一个格式化字符串,并且整个数组被包含在方括号[] 中。

参数

        int[] a:基本类型数组,将基本类型数组转换为它的字符串表示的形式。

        Object[] a:对象数组,调用每个对象的toString()方法来获取其字符串表示形式。

返回值

        字符串

举例
import java.util.Arrays;

public class xx {
	public static void main(String[] args) {
		Integer[] n1 = {5,7,9,1,5,4,8,6,3,2};
		System.out.println(Arrays.toString(n1));
	}
}

运行结果:

源代码解读

        创建一个StringBuilder对象,用于构建最终的字符串表示,提高字符串拼接的效率。向StringBuilder对象b中追加一个'[',作为数组字符串的开头,for循环,遍历数组并追加每个元素,将当前索引 i 对应的数组元素追加到 StringBuilder 中,检查当前索引i是否已经是数组的最后一个索引,如果是数组的最后一个元素,则追加一个右方括号 ']',并将 StringBuilder 对象转换为字符串表示,然后返回这个字符串。toString 方法会返回一个形如 [元素1, 元素2, ..., 元素n] 的字符串,其中 元素1 到 元素n 是数组中的各个元素。如果数组为空,则返回 [];如果数组为 null,则返回 "null"。

    public static String toString(Object[] a) {
        if (a == null)
            return "null";

        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

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

Arrays.deeptoString( )

作用

        打印输出多维数组

参数

        Object[] a:目标数组

返回值

        字符串

举例
import java.util.Arrays;

public class xx {
	public static void main(String[] args) {
		int n1[][]= {
				{5,7,9},
				{1,5,4},
				{8,6,3}
				};
		System.out.println(Arrays.deepToString(n1));
	}
}

运行结果:

源代码解读

        使用StringBuilder进行了元素的拼接,之后调用toString方法打印到控制台,只不过需要注意的是,如果是对象数组,需要重写对象的toString方法,不然打印的还是对象的内存地址。

    public static String deepToString(Object[] a) {
        if (a == null)
            return "null";

        int bufLen = 20 * a.length;
        if (a.length != 0 && bufLen <= 0)
            bufLen = Integer.MAX_VALUE;
        StringBuilder buf = new StringBuilder(bufLen);
        deepToString(a, buf, new HashSet<Object[]>());
        return buf.toString();
    }
private static void deepToString(Object[] a, StringBuilder buf,
                                     Set<Object[]> dejaVu) {
        if (a == null) {
            buf.append("null");
            return;
        }
        int iMax = a.length - 1;
        if (iMax == -1) {
            buf.append("[]");
            return;
        }

        dejaVu.add(a);
        buf.append('[');
        for (int i = 0; ; i++) {

            Object element = a[i];
            if (element == null) {
                buf.append("null");
            } else {
                Class<?> eClass = element.getClass();

                if (eClass.isArray()) {
                    if (eClass == byte[].class)
                        buf.append(toString((byte[]) element));
                    else if (eClass == short[].class)
                        buf.append(toString((short[]) element));
                    else if (eClass == int[].class)
                        buf.append(toString((int[]) element));
                    else if (eClass == long[].class)
                        buf.append(toString((long[]) element));
                    else if (eClass == char[].class)
                        buf.append(toString((char[]) element));
                    else if (eClass == float[].class)
                        buf.append(toString((float[]) element));
                    else if (eClass == double[].class)
                        buf.append(toString((double[]) element));
                    else if (eClass == boolean[].class)
                        buf.append(toString((boolean[]) element));
                    else { // element is an array of object references
                        if (dejaVu.contains(element))
                            buf.append("[...]");
                        else
                            deepToString((Object[])element, buf, dejaVu);
                    }
                } else {  // element is non-null and not an array
                    buf.append(element.toString());
                }
            }
            if (i == iMax)
                break;
            buf.append(", ");
        }
        buf.append(']');
        dejaVu.remove(a);
    }

 

  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值