此博客用于个人学习,来源于书籍和网上,对知识点进行一个整理。
重要的工具类—— Arrays 类:
Java.uti.Arrays 是 JDK 提供的一个工具类,用来处理数组的各种方法,而且每个方法基本上都是静态方法,能直接通过类名 Arrays 调用。
1. asList 方法:
该方法的作用是返回由指定数组支持的固定大小列表。
/**
* 返回指定数组支持的固定大小列表:要注意到这里的参数是泛型
*
* Returns a fixed-size list backed by the specified array. (Changes to
* the returned list "write through" to the array.) This method acts
* as bridge between array-based and collection-based APIs, in
* combination with {@link Collection#toArray}. The returned list is
* serializable and implements {@link RandomAccess}.
*
* <p>This method also provides a convenient way to create a fixed-size
* list initialized to contain several elements:
* <pre>
* List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
* </pre>
*
* @param <T> the class of the objects in the array
* @param a the array by which the list will be backed
* @return a list view of the specified array
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
要注意的是:这个 ArrayList 不是常用的集合类 Java.util.ArrayList,而是 Arrays 的一个内部类。
1)返回的 ArrayList 数组是一个定长列表,只能对其进行查看和修改,但是不能进行添加或者删除操作。如果对其进行增加或者删除操作,都会调用其父类 AbstractList 对应的方法,最终会抛出异常。
2)在 Arrays.asList 源码中,方法声明为 <T> List<T> asList(T…a)。该方法接收一个可变参数,并且这个可变参数类型是作为泛型的参数。基本数据类型是不能作为泛型的参数的,但是数组是引用类型,所以数组是泛型化的,于是 int[] 作为整个参数类型,而不是 int 作为参数类型。
3)返回的列表 ArrayList 里面的元素都是引用,而不是独立出来的对象,这里修改集合的内容,原数组的内容也会发生改变。
ArrayList.asList 比较适合那些已经有数组或者一些元素,而需要快速构建一个 List,只用于读取操作,而不进行添加或者删除操作的场景。
2. sort 方法:
该方法是用于数组排序,在 Arrays 类中有该方法的一系列重载方法,它能对7种基本数据类型,包括 byte、char、double、float、int、long、short 进行排序,后遇 Object 类型(实现了 Comparable 接口)以及比较器 Comparator。
/**
* 将数组按照升序的顺序排列
*
* Sorts the specified array into ascending numerical order.
*
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
*
* @param a the array to be sorted
*/
public static void sort(int[] a) {
DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
在 Arrays.sort 方法内部调用 DualPivotQuicksort.sort 方法,这个方法的源码很长,分别对于数组的长度进行了各种算法的划分,包括快速排序、插入排序、冒泡排序等。
3. binarySearch 方法:
用 binarySearch 方法查找数组中的某个元素,该方法和 sort 方法一样,适用于各种数组类型以及对象。
/**
* 查找数组中的某个元素,适用于各种基本数据类型以及对象
*
* Searches a range of
* the specified array of floats for the specified value using
* the binary search algorithm.
* The range must be sorted
* (as by the {@link #sort(float[], int, int)} method)
* prior to making this call. If
* it is not sorted, the results are undefined. If the range contains
* multiple elements with the specified value, there is no guarantee which
* one will be found. This method considers all NaN values to be
* equivalent and equal.
*
* @param a the array to be searched
* @param fromIndex the index of the first element (inclusive) to be
* searched
* @param toIndex the index of the last element (exclusive) to be searched
* @param key the value to be searched for
* @return index of the search key, if it is contained in the array
* within the specified range;
* otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
* <i>insertion point</i> is defined as the point at which the
* key would be inserted into the array: the index of the first
* element in the range greater than the key,
* or <tt>toIndex</tt> if all
* elements in the range are less than the specified key. Note
* that this guarantees that the return value will be >= 0 if
* and only if the key is found.
* @throws IllegalArgumentException
* if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0 or toIndex > a.length}
* @since 1.6
*/
public static int binarySearch(float[] a, int fromIndex, int toIndex,
float key) {
rangeCheck(a.length, fromIndex, toIndex);
return binarySearch0(a, fromIndex, toIndex, key);
}
// Like public version, but without range checks.
private static int binarySearch0(float[] a, int fromIndex, int toIndex,
float key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;//取中间值下标
float midVal = a[mid];//取中间值
if (midVal < key)
low = mid + 1; // Neither val is NaN, thisVal is smaller
else if (midVal > key)
high = mid - 1; // Neither val is NaN, thisVal is larger
else {
int midBits = Float.floatToIntBits(midVal);
int keyBits = Float.floatToIntBits(key);
if (midBits == keyBits) // Values are equal
return mid; // Key found
else if (midBits < keyBits) // (-0.0, 0.0) or (!NaN, NaN)
low = mid + 1;
else // (0.0, -0.0) or (NaN, !NaN)
high = mid - 1;
}
}
return -(low + 1); // key not found.
}
4. copyOf 方法:
copyOf 方法用于拷贝数组元素,底层采用 System.arraycopy() 实现,这是一个 native 方法。
/**
* Copies an array from the specified source array, beginning at the
* specified position, to the specified position of the destination array.
* A subsequence of array components are copied from the source
* array referenced by <code>src</code> to the destination array
* referenced by <code>dest</code>. The number of components copied is
* equal to the <code>length</code> argument. The components at
* positions <code>srcPos</code> through
* <code>srcPos+length-1</code> in the source array are copied into
* positions <code>destPos</code> through
* <code>destPos+length-1</code>, respectively, of the destination
* array.
* <p>
* If the <code>src</code> and <code>dest</code> arguments refer to the
* same array object, then the copying is performed as if the
* components at positions <code>srcPos</code> through
* <code>srcPos+length-1</code> were first copied to a temporary
* array with <code>length</code> components and then the contents of
* the temporary array were copied into positions
* <code>destPos</code> through <code>destPos+length-1</code> of the
* destination array.
* <p>
* If <code>dest</code> is <code>null</code>, then a
* <code>NullPointerException</code> is thrown.
* <p>
* If <code>src</code> is <code>null</code>, then a
* <code>NullPointerException</code> is thrown and the destination
* array is not modified.
* <p>
* Otherwise, if any of the following is true, an
* <code>ArrayStoreException</code> is thrown and the destination is
* not modified:
* <ul>
* <li>The <code>src</code> argument refers to an object that is not an
* array.
* <li>The <code>dest</code> argument refers to an object that is not an
* array.
* <li>The <code>src</code> argument and <code>dest</code> argument refer
* to arrays whose component types are different primitive types.
* <li>The <code>src</code> argument refers to an array with a primitive
* component type and the <code>dest</code> argument refers to an array
* with a reference component type.
* <li>The <code>src</code> argument refers to an array with a reference
* component type and the <code>dest</code> argument refers to an array
* with a primitive component type.
* </ul>
* <p>
* Otherwise, if any of the following is true, an
* <code>IndexOutOfBoundsException</code> is
* thrown and the destination is not modified:
* <ul>
* <li>The <code>srcPos</code> argument is negative.
* <li>The <code>destPos</code> argument is negative.
* <li>The <code>length</code> argument is negative.
* <li><code>srcPos+length</code> is greater than
* <code>src.length</code>, the length of the source array.
* <li><code>destPos+length</code> is greater than
* <code>dest.length</code>, the length of the destination array.
* </ul>
* <p>
* Otherwise, if any actual component of the source array from
* position <code>srcPos</code> through
* <code>srcPos+length-1</code> cannot be converted to the component
* type of the destination array by assignment conversion, an
* <code>ArrayStoreException</code> is thrown. In this case, let
* <b><i>k</i></b> be the smallest nonnegative integer less than
* length such that <code>src[srcPos+</code><i>k</i><code>]</code>
* cannot be converted to the component type of the destination
* array; when the exception is thrown, source array components from
* positions <code>srcPos</code> through
* <code>srcPos+</code><i>k</i><code>-1</code>
* will already have been copied to destination array positions
* <code>destPos</code> through
* <code>destPos+</code><i>k</I><code>-1</code> and no other
* positions of the destination array will have been modified.
* (Because of the restrictions already itemized, this
* paragraph effectively applies only to the situation where both
* arrays have component types that are reference types.)
*
* @param src the source array.
* @param srcPos starting position in the source array.
* @param dest the destination array.
* @param destPos starting position in the destination data.
* @param length the number of array elements to be copied.
* @exception IndexOutOfBoundsException if copying would cause
* access of data outside array bounds.
* @exception ArrayStoreException if an element in the <code>src</code>
* array could not be stored into the <code>dest</code> array
* because of a type mismatch.
* @exception NullPointerException if either <code>src</code> or
* <code>dest</code> is <code>null</code>.
*/
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
- src:源数组
- srcPos:源数组要复制的起始位置
- dest:目的数组
- destPos:目的数组放置的起始位置
- length:复制的长度
src 和 dest 都必须是同类型或者可以进行转换类型的数组。
5. equals 和 deepEquals 方法:
equals 用来比较两个数组中对应位置的每个元素是否相等。
先看 int 类型的数组比较,源码如下:
/**
* Returns <tt>true</tt> if the two specified arrays of ints are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
* of elements in the two arrays are equal. In other words, two arrays
* are equal if they contain the same elements in the same order. Also,
* two array references are considered equal if both are <tt>null</tt>.<p>
*
* @param a one array to be tested for equality
* @param a2 the other array to be tested for equality
* @return <tt>true</tt> if the two arrays are equal
*/
public static boolean equals(int[] a, int[] a2) {
//数组引用相等,则里面的元素一定相等
if (a==a2)
return true;
//两个数组其中一个为 null,返回 false
if (a==null || a2==null)
return false;
int length = a.length;
//两个数组长度不等,返回 false
if (a2.length != length)
return false;
//通过 for 循环依次比较每个元素是否相等
for (int i=0; i<length; i++)
if (a[i] != a2[i])
return false;
return true;
}
再看对象数组的比较:
/**
* Returns <tt>true</tt> if the two specified arrays of Objects are
* <i>equal</i> to one another. The two arrays are considered equal if
* both arrays contain the same number of elements, and all corresponding
* pairs of elements in the two arrays are equal. Two objects <tt>e1</tt>
* and <tt>e2</tt> are considered <i>equal</i> if <tt>(e1==null ? e2==null
* : e1.equals(e2))</tt>. In other words, the two arrays are equal if
* they contain the same elements in the same order. Also, two array
* references are considered equal if both are <tt>null</tt>.<p>
*
* @param a one array to be tested for equality
* @param a2 the other array to be tested for equality
* @return <tt>true</tt> if the two arrays are equal
*/
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;
}
deepEquals 也是用来比较两个数组的元素是否相等,不过 deepEquals 能够比较多维数组,而且是任意层次的嵌套数组。
6. fill 方法:
该方法用于给数组赋值,并能指定某个赋值范围。
/**
* 给a数组所有元素赋值val
*
* Assigns the specified int value to each element of the specified array
* of ints.
*
* @param a the array to be filled
* @param val the value to be stored in all elements of the array
*/
public static void fill(int[] a, int val) {
for (int i = 0, len = a.length; i < len; i++)
a[i] = val;
}
/**
* 给从fromIndex开始的下标,toIndex-1结尾的下标都赋值val,左闭右开
*
* Assigns the specified int value to each element of the specified
* range of the specified array of ints. The range to be filled
* extends from index <tt>fromIndex</tt>, inclusive, to index
* <tt>toIndex</tt>, exclusive. (If <tt>fromIndex==toIndex</tt>, the
* range to be filled is empty.)
*
* @param a the array to be filled
* @param fromIndex the index of the first element (inclusive) to be
* filled with the specified value
* @param toIndex the index of the last element (exclusive) to be
* filled with the specified value
* @param val the value to be stored in all elements of the array
* @throws IllegalArgumentException if <tt>fromIndex > toIndex</tt>
* @throws ArrayIndexOutOfBoundsException if <tt>fromIndex < 0</tt> or
* <tt>toIndex > a.length</tt>
*/
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;
}
7. toString 和 deepToString 方法:
toString 用来打印一位数组的元素,而 deepToString 用来打印多层嵌套的数组元素。
/**
* 打印一维数组的元素
*
* Returns a string representation of the contents of the specified array.
* The string representation consists of a list of the array's elements,
* enclosed in square brackets (<tt>"[]"</tt>). Adjacent elements are
* separated by the characters <tt>", "</tt> (a comma followed by a
* space). Elements are converted to strings as by
* <tt>String.valueOf(int)</tt>. Returns <tt>"null"</tt> if <tt>a</tt> is
* <tt>null</tt>.
*
* @param a the array whose string representation to return
* @return a string representation of <tt>a</tt>
* @since 1.5
*/
public static String toString(int[] 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(a[i]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
/**
* 用来打印多层嵌套的数组元素
*
* Returns a string representation of the "deep contents" of the specified
* array. If the array contains other arrays as elements, the string
* representation contains their contents and so on. This method is
* designed for converting multidimensional arrays to strings.
*
* <p>The string representation consists of a list of the array's
* elements, enclosed in square brackets (<tt>"[]"</tt>). Adjacent
* elements are separated by the characters <tt>", "</tt> (a comma
* followed by a space). Elements are converted to strings as by
* <tt>String.valueOf(Object)</tt>, unless they are themselves
* arrays.
*
* <p>If an element <tt>e</tt> is an array of a primitive type, it is
* converted to a string as by invoking the appropriate overloading of
* <tt>Arrays.toString(e)</tt>. If an element <tt>e</tt> is an array of a
* reference type, it is converted to a string as by invoking
* this method recursively.
*
* <p>To avoid infinite recursion, if the specified array contains itself
* as an element, or contains an indirect reference to itself through one
* or more levels of arrays, the self-reference is converted to the string
* <tt>"[...]"</tt>. For example, an array containing only a reference
* to itself would be rendered as <tt>"[[...]]"</tt>.
*
* <p>This method returns <tt>"null"</tt> if the specified array
* is <tt>null</tt>.
*
* @param a the array whose string representation to return
* @return a string representation of <tt>a</tt>
* @see #toString(Object[])
* @since 1.5
*/
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();
}