这个类竟然有8000多行,太不科学了,不过分析得知大量代码是重复的,换一下类型(8大基本类型,除部分代码外,全部重复,因此下面的示例代码只给出int类型的实现及object类型的实现)
属性
- 各种类型的空数组,包括空对象数组,空类数组,空字符串数组,8大基本类型数组,8大基本类封装类数组,这些数组的命名规则为
EMPTY_XXX_ARRAY
,其中,XXX的含义为:对象(OBJECT
),类(CLASS
),基本类型(BYTE、CHAR、SHORT、INT、LONG、FLOAT、DOUBLE、BOOLEAN
),基本类型封装类型(BYTE_OBJECT、CHARACTER_OBJECT、SHORT_OBJECT、INTEGER_OBJECT、LONG_OBJECT、FLOAT_OBJECT、DOUBLE_OBJECT、BOOLEAN_OBJECT
)
示例如下:
public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]
public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class[0]
public static final String[] EMPTY_STRING_ARRAY = new String[0]
public static final long[] EMPTY_LONG_ARRAY = new long[0]
public static final Long[] EMPTY_LONG_OBJECT_ARRAY = new Long[0]
- 用于指示一个元素不在数组中的标志,
INDEX_NOT_FOUND
:
public static final int INDEX_NOT_FOUND = -1;
构造方法
该方法用于javaBean,用户不应该创建ArrayUtils实例,因为ArrayUtils的方法都是静态的
public ArrayUtils() {
super();
}
相关方法
toString方法
- toString(final Object array),当数组为null时,返回”{}”
//核心代码
return toString(array, "{}");
- toString(final Object array, final String stringIfNull),调用ToStringBuilder实现
//核心代码
if (array == null) {
return stringIfNull;
}
return new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString();
hashCode方法
- hashCode(final Object array),调用HashCodeBuilder实现
//核心代码
return new HashCodeBuilder().append(array).toHashCode();
toMap方法
- Map<Object, Object> toMap(final Object[] array),接受两种array元素类型:
- Map.Entry<?, ?>
- Object[],元素个数要大于等于2,只取第一第二个元素,第一个作为key,第二个作为value
//核心代码
final Map<Object, Object> map = new HashMap<>((int) (array.length * 1.5));
for (int i = 0; i < array.length; i++) {
final Object object = array[i];
if (object instanceof Map.Entry<?, ?>) {
final Map.Entry<?,?> entry = (Map.Entry<?,?>) object;
map.put(entry.getKey(), entry.getValue());
} else if (object instanceof Object[]) {
final Object[] entry = (Object[]) object;
if (entry.length < 2) {
throw new IllegalArgumentException("Array element " + i + ", '"
+ object
+ "', has a length less than 2");
}
map.put(entry[0], entry[1]);
} else {
throw new IllegalArgumentException("Array element " + i + ", '"
+ object
+ "', is neither of type Map.Entry nor an Array");
}
}
return map;
toArray方法
- toArray(final T… items),将输入的参数转换成数组
clone方法
调用array的clone方法实现,有判空操作
//核心代码
return array == null ? null : array.clone();
nullToEmpty方法
- nullToEmpty(final T[] array, final Class
//核心代码
if (array == null) {
return type.cast(Array.newInstance(type.getComponentType(), 0));
}
return array;
- nullToEmpty(final T[] array),将null或长度为0的array转换成同类型的空数组对象,若传入的array对象非空,则原样返回
//核心代码
return isEmpty(array) ? EMPTY_OBJECT_ARRAY : array;
subarray方法
- 核心是调用System.arraycopy方法,startIndexInclusive小于0则从0开始,endIndexExclusive大于array.length,则到array.length截止
//核心代码
final int newSize = endIndexExclusive - startIndexInclusive;
final Class<?> type = array.getClass().getComponentType();
if (newSize <= 0) {
@SuppressWarnings("unchecked") // OK, because array is of type T
final T[] emptyArray = (T[]) Array.newInstance(type, 0);
return emptyArray;
}
@SuppressWarnings("unchecked") // OK, because array is of type T
final
T[] subarray = (T[]) Array.newInstance(type, newSize);
System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
return subarray;
isSameLength方法
判断两个数组长度是否相同
//核心代码
return getLength(array1) == getLength(array2);
public static int getLength(final Object array) {
return array == null ? 0 : Array.getLength(array);
}
isSameType方法
public static boolean isSameType(final Object array1, final Object array2) {
if (array1 == null || array2 == null) {
throw new IllegalArgumentException("The Array must not be null");
}
return array1.getClass().getName().equals(array2.getClass().getName());
}
reverse方法
- 核心方法是交换第i个元素与第lastIndex-i个元素
public static void reverse(final Object[] array) {
if (array == null) {
return;
}
reverse(array, 0, array.length);
}
public static void reverse(final boolean[] array, final int startIndexInclusive, final int endIndexExclusive) {
if (array == null) {
return;
}
int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
int j = Math.min(array.length, endIndexExclusive) - 1;
boolean tmp;
while (j > i) {
tmp = array[j];
array[j] = array[i];
array[i] = tmp;
j--;
i++;
}
}
swap方法
- 交换两个元素值的位置
public static void swap(final Object[] array, final int offset1, final int offset2) {
if (array == null || array.length == 0) {
return;
}
swap(array, offset1, offset2, 1);
}
//交换从offset1开始的len个元素与offset2开始的len个元素
len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
for (int i = 0; i < len; i++, offset1++, offset2++) {
final boolean aux = array[offset1];
array[offset1] = array[offset2];
array[offset2] = aux;
}
shift方法
- 在子数组范围内向右循环移动n个元素,其实现是调用swap方法,比旋转左边len-n个子元素,再旋转右边n个元素,最后再旋转所有len个元素慢3倍
public static void shift(final Object[] array, final int offset) {
if (array == null) {
return;
}
shift(array, 0, array.length, offset);
}
//原有调用swap的方法省略
//给出rotate方式实现,比swap方式快3倍
public static void rotate(int[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
rotate(array, startIndexInclusive, endIndexExclusive - offset);
rotate(array, endIndexExclusive - offset, endIndexExclusive);
rotate(array, startIndexInclusive, endIndexExclusive);
}
public static void rotate(int[] array, int startIndexInclusive, int endIndexExclusive) {
if (array == null || array.length == 0 || startIndexInclusive >= array.length || endIndexExclusive >= array.length) {
return;
}
if (startIndexInclusive < 0) {
startIndexInclusive = 0;
}
if (endIndexExclusive < 0) {
endIndexExclusive = 0;
}
int low = startIndexInclusive;
int high = endIndexExclusive - 1;
while (low < high) {
int tmp = array[low];
array[low] = array[high];
array[high] = tmp;
low++;
high--;
}
}
indexOf、lastIndexOf方法
- 遍历一遍数组,找不到就返回INDEX_NOT_FOUND
- 浮点类型多一个精度参数,用以判断偏差在什么范围内为相等
- 最后一个参数startIndex默认为0,若有带入,则指示从哪个位置开始搜索
int indexOf(final boolean[] array, final boolean valueToFind, int startIndex)
contains方法
- 调用indexOf方法,判断返回值是否为INDEX_NOT_FOUND
toPrimitive方法
- 将封箱类型数组转换成基本类型数组,第一个方法元素不能为空(因为有调用获取值得方法),否则会抛出NPE;第二个方法可以在元素为空时转成设定的默认值
//元素不能为空
public static char[] toPrimitive(final Character[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
return EMPTY_CHAR_ARRAY;
}
final char[] result = new char[array.length];
for (int i = 0; i < array.length; i++) {
result[i] = array[i].charValue();
}
return result;
}
//元素可为空,为空时用valueForNull填充
//核心代码
for (int i = 0; i < array.length; i++) {
final Character b = array[i];
result[i] = (b == null ? valueForNull : b.charValue());
}
return result;
toObject方法
- 将基本类型数组转换成封箱类型数组
public static Character[] toObject(final char[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
return EMPTY_CHARACTER_OBJECT_ARRAY;
}
final Character[] result = new Character[array.length];
for (int i = 0; i < array.length; i++) {
result[i] = Character.valueOf(array[i]);
}
return result;
}
isEmpty方法、isNotEmpty方法
- isEmpty判断数组是否为null或长度是否为0
- isNotEmpty与isEmpty相反
addAll方法
- 创建一个新数组,包含传入的参数数组的全部元素
- 核心是System.arraycopy方法
add方法
- 创建一个新数组,长度是原始数组长度加1,新数组按原数组顺序容纳其所有元素
- 在新数组最后一个位置插入新元素
remove方法
- 删除指定位置的元素
- 调用System.arraycopy实现
//核心代码
public static int[] remove(final int[] array, final int index) {
return (int[]) remove((Object) array, index);
}
private static Object remove(final Object array, final int index) {
final int length = getLength(array);
if (index < 0 || index >= length) {
throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
}
final Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
System.arraycopy(array, 0, result, 0, index);
if (index < length - 1) {
System.arraycopy(array, index + 1, result, index, length - index - 1);
}
return result;
}
- removeElement方法;可进行批量删除(调用removeAll实现)
- removeAll方法删除指定位置的元素,一次可以删除多个
removeElement方法
- 先查找待删除元素第一次出现的位置,然后调用remove方法删除元素
final int index = indexOf(array, element);
if (index == INDEX_NOT_FOUND) {
return clone(array);
}
return remove(array, index);
public static short[] removeElements(final short[] array, final short... values) {
if (isEmpty(array) || isEmpty(values)) {
return clone(array);
}
final HashMap<Short, MutableInt> occurrences = new HashMap<>(values.length);
for (final short v : values) {
final Short boxed = Short.valueOf(v);
final MutableInt count = occurrences.get(boxed);
if (count == null) {
occurrences.put(boxed, new MutableInt(1));
} else {
count.increment();
}
}
final BitSet toRemove = new BitSet();
for (int i = 0; i < array.length; i++) {
final short key = array[i];
final MutableInt count = occurrences.get(key);
if (count != null) {
if (count.decrementAndGet() == 0) {
occurrences.remove(key);
}
toRemove.set(i);
}
}
return (short[]) removeAll(array, toRemove);
}
removeAll方法
public static byte[] removeAll(final byte[] array, final int... indices) {
return (byte[]) removeAll((Object) array, indices);
}
static Object removeAll(final Object array, final int... indices) {
final int length = getLength(array);
int diff = 0; // number of distinct indexes, i.e. number of entries that will be removed
//对indices进行拷贝并排序
// identify length of result array
if (isNotEmpty(clonedIndices)) {
//计算需要删除元素的个数diff
}
// create result array,并循环调用System.arraycopy
return result;
}
removeElements方法
- 先找出所有要删除元素的位置,然调用removeAll方法
public static byte[] removeElements(final byte[] array, final byte... values) {
if (isEmpty(array) || isEmpty(values)) {
return clone(array);
}
final Map<Byte, MutableInt> occurrences = new HashMap<>(values.length);
for (final byte v : values) {
final Byte boxed = Byte.valueOf(v);
final MutableInt count = occurrences.get(boxed);
if (count == null) {
occurrences.put(boxed, new MutableInt(1));
} else {
count.increment();
}
}
final BitSet toRemove = new BitSet();
for (int i = 0; i < array.length; i++) {
final byte key = array[i];
final MutableInt count = occurrences.get(key);
if (count != null) {
if (count.decrementAndGet() == 0) {
occurrences.remove(key);
}
toRemove.set(i);
}
}
return (byte[]) removeAll(array, toRemove);
}
isSorted方法
- 判断数组是否非降序排列
- 空数组及长度小于2的数组是非降序的
//核心代码
boolean previous = array[0];
final int n = array.length;
for (int i = 1; i < n; i++) {
final boolean current = array[i];
if (BooleanUtils.compare(previous, current) > 0) {
return false;
}
previous = current;
}
return true;
removeAllOccurences方法
- 移除数组中出现的所有指定元素
- 先查找所有满足条件的元素的位置,然后调用removeAll
//核心代码
return removeAll(array, Arrays.copyOf(indices, count));
toStringArray
- 转换成字符串数组,若元素为空,则跑出NPE,但若是指定了元素为空时的默认值,则用默认值填充
//核心代码1,元素不能为空
//String[] toStringArray(final Object[] array)
final String[] result = new String[array.length];
for (int i = 0; i < array.length; i++) {
result[i] = array[i].toString();
}
//核心代码2,有填充
//String[] toStringArray(final Object[] array, final String valueForNullElements)
final String[] result = new String[array.length];
for (int i = 0; i < array.length; i++) {
final Object object = array[i];
result[i] = (object == null ? valueForNullElements : object.toString());
}
insert方法
- 创建一个新数组
- 调用System.arraycopy方法拷贝原数组插入位置之前的所有元素
- 在指定位置插入新元素
- 调用System.arraycopy方法拷贝原数组剩余的元素
//核心代码
//拷贝所有待插入元素到新数组index开始的位置
System.arraycopy(values, 0, result, index, values.length);
//拷贝原数组前index个元素到新数组
if (index > 0) {
System.arraycopy(array, 0, result, 0, index);
}
//拷贝原数组index及之后的元素到新数组
if (index < array.length) {
System.arraycopy(array, index, result, index + values.length, array.length - index);
}
shuffle方法
- 打乱数组元素,在原数组上操作
- 遍历一遍数组,与随机生成的位置上的元素交换
//核心代码
//遍历数组元素,使得元素与随机位置上的元素进行交换
for (int i = array.length; i > 1; i--) {
swap(array, i - 1, random.nextInt(i), 1);
}