源码解析(1)-数组工具类解析

​一、jdk原生Arrays分析(版本1.8.0)

1.1 引入

Arrays是jdk原生对数组操作的工具类,相信在项目中经常可以看到Arrays.sort , Arrays.binarySearch,Arrays.fill等方法。但是没有对Arrays的源码进行进一步了解,为了让自己有对Arrays有更深的了解,所以写这篇文章介绍我对Arrays源码的分析。

1.2 源码解析

1.2.1 构造器

// Arrays是工具类,没有必要创建对应,推荐在工具类中都加上这样的代码

private Arrays() {}

1.2.2 主要方法

Arrays方法中有很多重载方法,为了避免重复,取其中具有代表性的方法进行讲解
1.2.2.1 rangeCheck
 /**
     * @param arrayLength 数组自身长度
     * @param fromIndex 起始索引位置
     * @param toIndex 结束索引位置
     * 注意如果校验不成功直接抛出异常
     */
    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);
        }
    }
1.2.2.2 sort
    public static void sort(double[] a, int fromIndex, int toIndex) {
       // 校验(前面已经介绍了)
        rangeCheck(a.length, fromIndex, toIndex);
        // 双轴快速排序(会重新写一篇文章介绍这个算法)
        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
    }
1.2.2.3 parallelSort
   public static void parallelSort(double[] a) {
        int n = a.length, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
		// commonPoolParallelism : 取决于可用内核的数量
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
        else
			//当数组长度大于 8192 时使用并行排序
            new ArraysParallelSortHelpers.FJDouble.Sorter
                (null, a, new double[n], 0, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

2.2.4 binarySearch

    // 二分查找
    public static int binarySearch(double[] a, int fromIndex, int toIndex,
                                   double key) {
        rangeCheck(a.length, fromIndex, toIndex);
		// 主要方法
        return binarySearch0(a, fromIndex, toIndex, key);
    }
	
	/**
     * @param a 数组(需要已经排序)
	 * @param fromIndex 数组起始索引(包含)
	 * @param toIndex 数组结束索引(不包含)
	 * @param key 查找数字
	 */
	  private static int binarySearch0(double[] a, int fromIndex, int toIndex,double key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            double midVal = a[mid]; // 中间值

            if (midVal < key)
                low = mid + 1;  // 如果中间值小于需要查找的值,说明已经从中间索引的后位开始查找
            else if (midVal > key)
                high = mid - 1; // 如果中间值大于需要查找的值,说明已经从中间索引的前位开始查找
            else {
				// double类型或者float类型的数据不能直接通过==,进行比较
				// 将double类型的值转化为long类型的数据比较
                long midBits = Double.doubleToLongBits(midVal);
                long keyBits = Double.doubleToLongBits(key);
                if (midBits == keyBits)     
                    return mid;             
                else if (midBits < keyBits) 
                    low = mid + 1;
                else                        
                    high = mid - 1;
            }
        }
		// 如果找不到返回负数
        return -(low + 1);
    }
1.2.2.5 fill
     /**
     * 将数组的某一部分填充为固定值
     */
	public static void fill(double[] a, int fromIndex, int toIndex,double val){
        rangeCheck(a.length, fromIndex, toIndex);
        for (int i = fromIndex; i < toIndex; i++)
            a[i] = val;
    }

2.2.6 copyOf

    /**
	 * 数组拷贝
	 * @param original 需要拷贝的数组
	 * @param newLength 需要拷贝的长度
	 * @param newType 拷贝之后的数组类型
	 */
	public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
			// Array.newInstance根据数组元素类型和长度创建数组对象
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
			// 拷贝数组
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

二、ArrayUtils(common-lang3)

2.1 数组转换为Map集合

     /**
      * 将数组转换为Map
      */	  
     public static Map<Object, Object> toMap(Object[] array) {
        if (array == null) {
            return null;
        } else {
			// hashmap默认的装载因子为0.75,如果设置和array长度一样,就会触发一次扩容
            Map<Object, Object> map = new HashMap((int)((double)array.length * 1.5D));

            for(int i = 0; i < array.length; ++i) {
                Object object = array[i];
				// 如果每个元素就是Entry,直接添加到map中
                if (object instanceof Entry) {
                    Entry<?, ?> entry = (Entry)object;
                    map.put(entry.getKey(), entry.getValue());
                } else {
                    if (!(object instanceof Object[])) {
                        throw new IllegalArgumentException("Array element " + i + ", '" + object + "', is neither of type Map.Entry nor an Array");
                    }
                    
                    Object[] entry = (Object[])((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]);
                }
            }

            return map;
        }
    }

2.2 子数组

    /**
	 * 获取子数组
	 * @param array 原数组
	 * @param startIndexInclusive 起始索引位置
	 * @param endIndexExclusive 结束索引位置
	 */
	public static <T> T[] subarray(T[] array, int startIndexInclusive, int endIndexExclusive) {
        if (array == null) {
            return null;
        } else {
			// 修复索引
            if (startIndexInclusive < 0) {
                startIndexInclusive = 0;
            }

            if (endIndexExclusive > array.length) {
                endIndexExclusive = array.length;
            }

            int newSize = endIndexExclusive - startIndexInclusive;
			// 元素类型
            Class<?> type = array.getClass().getComponentType();
            Object[] subarray;
            if (newSize <= 0) {
                subarray = (Object[])((Object[])Array.newInstance(type, 0));
                return subarray;
            } else {
				// 创建指定大小的数组
                subarray = (Object[])((Object[])Array.newInstance(type, newSize));
                System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
                return subarray;
            }
        }
    }

2.3 数组反转

    /**
     * 数组反转
	 * @param array 数组
	 * @param startIndexInclusive 起始索引
	 * @param endIndexExclusive 结束索引
     */	 
   public static void reverse(Object[] array, int startIndexInclusive, int endIndexExclusive) {
        if (array != null) {
	    // 修复索引
            int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
           
            for(int j = Math.min(array.length, endIndexExclusive) - 1; j > i; ++i) {
		// 交换数据
                Object tmp = array[j];
                array[j] = array[i];
                array[i] = tmp;
                --j;
            }

        }
    }

4 数组下标位置

    /**
	 * 数组元素下标位置
	 * @param array 需要查找的数组
	 * @param objectToFind 查找元素
	 * @param startIndex 起始索引
	 * @return 没有找到返回-1
	 */
	public static int indexOf(Object[] array, Object objectToFind, int startIndex) {
        if (array == null) {
            return -1;
        } else {
			// 起始索引
            if (startIndex < 0) {
                startIndex = 0;
            }

            int i;
			// 考虑null
            if (objectToFind == null) {
                for(i = startIndex; i < array.length; ++i) {
                    if (array[i] == null) {
                        return i;
                    }
                }
            } else {
				// 遍历查找
                for(i = startIndex; i < array.length; ++i) {
                    if (objectToFind.equals(array[i])) {
                        return i;
                    }
                }
            }

            return -1;
        }
    }

2.5 合并数组

    /**
	 * 数组合并
	 * 
	 */
	public static <T> T[] addAll(T[] array1, T... array2) {
		// 返回拷贝的数组
        if (array1 == null) {
            return clone(array2);
        } else if (array2 == null) {
            return clone(array1);
        } else {
            Class<?> type1 = array1.getClass().getComponentType();
			// 创建两个数组长度和的数组
            T[] joinedArray = (Object[])((Object[])Array.newInstance(type1, array1.length + array2.length));
            System.arraycopy(array1, 0, joinedArray, 0, array1.length);

            try {
                System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
                return joinedArray;
            } catch (ArrayStoreException var6) {
                Class<?> type2 = array2.getClass().getComponentType();
				// Class.isAssignableFrom()是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的子类或接口。   
                if (!type1.isAssignableFrom(type2)) {
                    throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of " + type1.getName(), var6);
                } else {
                    throw var6;
                }
            }
        }
    }

三、自我扩展

3.1.将两个数组转换为Map集合

  /**
   * 将两个数组转换为Map
   *
   * @return
   */
  private static final Map EMPTY_MAP= new HashMap(0);
  public static <T, U> Map<T, U> toMap(T[] arr1, U[] arr2) {
      if (arr1 == null || arr2 == null) {
          return null;
      }
      if (arr1.length != arr2.length) {
          throw new IllegalArgumentException(
                  "arr1'length is not equals to arr2'length");
      }
      int len = arr1.length;
      if (0 == len) {
          return EMPTY_MAP;
      }
      Map<T, U> result = new HashMap<T, U>((int) (len * 1.5));
      for (int i = 0; i < len; i++) {
          result.put(arr1[i], arr2[i]);
      }
      return result;
  }

```​
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值