org.apache.commons.lang3.ArrayUtils源码分析

这个类竟然有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&ltObject, Object&gt 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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
commons-lang3.3.1.jar、Apache Commons包中的一个,包含了一些数据类型工具类,是java.lang.*的扩展。必须使用的jar包。为JRE5.0+的更好的版本所提供 Jar文件包含的类: META-INF/MANIFEST.MFMETA-INF/LICENSE.txtMETA-INF/NOTICE.txtorg.apache.commons.lang.ArrayUtils.class org.apache.commons.lang.BitField.class org.apache.commons.lang.BooleanUtils.class org.apache.commons.lang.CharEncoding.class org.apache.commons.lang.CharRange.class org.apache.commons.lang.CharSet.class org.apache.commons.lang.CharSetUtils.class org.apache.commons.lang.CharUtils.class org.apache.commons.lang.ClassUtils.class org.apache.commons.lang.Entities$ArrayEntityMap.class org.apache.commons.lang.Entities$BinaryEntityMap.class org.apache.commons.lang.Entities$EntityMap.class org.apache.commons.lang.Entities$HashEntityMap.class org.apache.commons.lang.Entities$LookupEntityMap.class org.apache.commons.lang.Entities$MapIntMap.class org.apache.commons.lang.Entities$PrimitiveEntityMap.class org.apache.commons.lang.Entities$TreeEntityMap.class org.apache.commons.lang.Entities.class org.apache.commons.lang.IllegalClassException.class org.apache.commons.lang.IncompleteArgumentException.class org.apache.commons.lang.IntHashMap$Entry.class org.apache.commons.lang.IntHashMap.class org.apache.commons.lang.LocaleUtils.class org.apache.commons.lang.NotImplementedException.class org.apache.commons.lang.NullArgumentException.class org.apache.commons.lang.NumberRange.class org.apache.commons.lang.NumberUtils.class org.apache.commons.lang.ObjectUtils$Null.class org.apache.commons.lang.ObjectUtils.class org.apache.commons.lang.RandomStringUtils.class org.apache.commons.lang.SerializationException.class org.apache.commons.lang.SerializationUtils.class org.apache.commons.lang.StringEscapeUtils.class org.apache.commons.lang.StringUtils.class org.apache.commons.lang.SystemUtils.class org.apache.commons.lang.UnhandledException.class org.apache.commons.lang.Validate.class org.apache.commons.lang.WordUtils.class org.apache.commons.lang.builder.CompareToBuilder.class org.apache.commons.lang.builder.EqualsBuilder.class org.apache.commons.lang.builder.HashCodeBuilder.class org.apache.commons.lang.builder.ReflectionToStringBuilder$1.class org.apache.commons.lang.builder.ReflectionToStringBuilder.class org.apache.commons.lang.builder.StandardToStringStyle.class org.apache.commons.lang.builder.ToStringBuilder.class org.apache.commons.lang.builder.ToStringStyle$DefaultToStringStyle.class org.apache.commons.lang.builder.ToStringStyle$MultiLineToStringStyle.class org.apache.commons.lang.builder.ToStringStyle$NoFieldNameToStringStyle.class org.apache.commons.lang.builder.ToStringStyle$ShortPrefixToStringStyle.class org.apache.commons.lang.builder.ToStringStyle$SimpleToStringStyle.class org.apache.commons.lang.builder.ToStringStyle.class org.apache.commons.lang.enum.Enum$Entry.class org.apache.commons.lang.enum.Enum.class org.apache.commons.lang.enum.EnumUtils.class org.apache.commons.lang.enum.ValuedEnum.class org.apache.commons.lang.enums.Enum$Entry.class org.apache.commons.lang.enums.Enum.class org.apache.commons.lang.enums.EnumUtils.class org.apache.commons.lang.enums.ValuedEnum.class org.apache.commons.lang.exception.ExceptionUtils.class org.apache.commons.lang.exception.Nestable.class org.apache.commons.lang.exception.NestableDelegate.class org.apache.commons.lang.exception.NestableError.class org.apache.commons.lang.exception.NestableException.class org.apache.commons.lang.exception.NestableRuntimeException.class org.apache.commons.lang.math.DoubleRange.class org.apache.commons.lang.math.FloatRange.class org.apache.commons.lang.math.Fraction.class org.apache.commons.lang.math.IntRange.class org.apache.commons.lang.math.JVMRandom.class org.apache.commons.lang.math.LongRange.class org.apache.commons.lang.math.NumberRange.class org.apache.commons.lang.math.NumberUtils.class org.apache.commons.lang.math.RandomUtils.class org.apache.commons.lang.math.Range.class org.apache.commons.lang.mutable.Mutable.class org.apache.commons.lang.mutable.MutableBoolean.class org.apache.commons.lang.mutable.MutableByte.class org.apache.commons.lang.mutable.MutableDouble.class org.apache.commons.lang.mutable.MutableFloat.class org.apache.commons.lang.mutable.MutableInt.class org.apache.commons.lang.mutable.MutableLong.class org.apache.commons.lang.mutable.MutableObject.class org.apache.commons.lang.mutable.MutableShort.class org.apache.commons.lang.text.CompositeFormat.class org.apache.commons.lang.text.StrBuilder$StrBuilderReader.class org.apache.commons.lang.text.StrBuilder$StrBuilderTokenizer.class org.apache.commons.lang.text.StrBuilder$StrBuilderWriter.class org.apache.commons.lang.text.StrBuilder.class org.apache.commons.lang.text.StrLookup$MapStrLookup.class org.apache.commons.lang.text.StrLookup.class org.apache.commons.lang.text.StrMatcher$CharMatcher.class org.apache.commons.lang.text.StrMatcher$CharSetMatcher.class org.apache.commons.lang.text.StrMatcher$NoMatcher.class org.apache.commons.lang.text.StrMatcher$StringMatcher.class org.apache.commons.lang.text.StrMatcher$TrimMatcher.class org.apache.commons.lang.text.StrMatcher.class org.apache.commons.lang.text.StrSubstitutor.class org.apache.commons.lang.text.StrTokenizer.class org.apache.commons.lang.time.DateFormatUtils.class org.apache.commons.lang.time.DateUtils$DateIterator.class org.apache.commons.lang.time.DateUtils.class org.apache.commons.lang.time.DurationFormatUtils$Token.class org.apache.commons.lang.time.DurationFormatUtils.class org.apache.commons.lang.time.FastDateFormat$CharacterLiteral.class org.apache.commons.lang.time.FastDateFormat$NumberRule.class org.apache.commons.lang.time.FastDateFormat$PaddedNumberField.class org.apache.commons.lang.time.FastDateFormat$Pair.class org.apache.commons.lang.time.FastDateFormat$Rule.class org.apache.commons.lang.time.FastDateFormat$StringLiteral.class org.apache.commons.lang.time.FastDateFormat$TextField.class org.apache.commons.lang.time.FastDateFormat$TimeZoneDisplayKey.class org.apache.commons.lang.time.FastDateFormat$TimeZoneNameRule.class org.apache.commons.lang.time.FastDateFormat$TimeZoneNumberRule.class org.apache.commons.lang.time.FastDateFormat$TwelveHourField.class org.apache.commons.lang.time.FastDateFormat$TwentyFourHourField.class org.apache.commons.lang.time.FastDateFormat$TwoDigitMonthField.class org.apache.commons.lang.time.FastDateFormat$TwoDigitNumberField.class org.apache.commons.lang.time.FastDateFormat$TwoDigitYearField.class org.apache.commons.lang.time.FastDateFormat$UnpaddedMonthField.class org.apache.commons.lang.time.FastDateFormat$UnpaddedNumberField.class org.apache.commons.lang.time.FastDateFormat.class org.apache.commons.lang.time.StopWatch.class

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值