/* * Copyright 2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package xyz.zhouxy.plusone.commons.util; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; public class ArrayTools { // #region - empty arrays public static final char[] EMPTY_CHAR_ARRAY = {}; public static final int[] EMPTY_INTEGER_ARRAY = {}; public static final long[] EMPTY_LONG_ARRAY = {}; public static final float[] EMPTY_FLOAT_ARRAY = {}; public static final double[] EMPTY_DOUBLE_ARRAY = {}; // #endregion // #region - isNullOrEmpty // isNullOrEmpty /** * 检查给定数组是否为空 * * @param arr 待检查的数组,可以为 {@code null} * @param 数组中元素的类型 * @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false} */ public static boolean isNullOrEmpty(@Nullable T[] arr) { return arr == null || arr.length == 0; } // isNullOrEmpty - float /** * 检查给定数组是否为空 * * @param arr 待检查的数组,可以为 {@code null} * @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false} */ public static boolean isNullOrEmpty(@Nullable float[] arr) { return arr == null || arr.length == 0; } // isNullOrEmpty - double /** * 检查给定数组是否为空 * * @param arr 待检查的数组,可以为 {@code null} * @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false} */ public static boolean isNullOrEmpty(@Nullable double[] arr) { return arr == null || arr.length == 0; } // isNullOrEmpty - byte /** * 检查给定数组是否为空 * * @param arr 待检查的数组,可以为 {@code null} * @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false} */ public static boolean isNullOrEmpty(@Nullable byte[] arr) { return arr == null || arr.length == 0; } // isNullOrEmpty - long /** * 检查给定数组是否为空 * * @param arr 待检查的数组,可以为 {@code null} * @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false} */ public static boolean isNullOrEmpty(@Nullable long[] arr) { return arr == null || arr.length == 0; } // isNullOrEmpty - int /** * 检查给定数组是否为空 * * @param arr 待检查的数组,可以为 {@code null} * @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false} */ public static boolean isNullOrEmpty(@Nullable int[] arr) { return arr == null || arr.length == 0; } // #endregion // #region - isNotEmpty // isNotEmpty /** * 检查给定数组是否不为空 * * @param arr 待检查的数组,可以为 {@code null} * @param 数组中元素的类型 * @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false} */ public static boolean isNotEmpty(@Nullable T[] arr) { return arr != null && arr.length > 0; } // isNotEmpty - float /** * 检查给定数组是否不为空 * * @param arr 待检查的数组,可以为 {@code null} * @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false} */ public static boolean isNotEmpty(@Nullable float[] arr) { return arr != null && arr.length > 0; } // isNotEmpty - double /** * 检查给定数组是否不为空 * * @param arr 待检查的数组,可以为 {@code null} * @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false} */ public static boolean isNotEmpty(@Nullable double[] arr) { return arr != null && arr.length > 0; } // isNotEmpty - byte /** * 检查给定数组是否不为空 * * @param arr 待检查的数组,可以为 {@code null} * @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false} */ public static boolean isNotEmpty(@Nullable byte[] arr) { return arr != null && arr.length > 0; } // isNotEmpty - long /** * 检查给定数组是否不为空 * * @param arr 待检查的数组,可以为 {@code null} * @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false} */ public static boolean isNotEmpty(@Nullable long[] arr) { return arr != null && arr.length > 0; } // isNotEmpty - int /** * 检查给定数组是否不为空 * * @param arr 待检查的数组,可以为 {@code null} * @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false} */ public static boolean isNotEmpty(@Nullable int[] arr) { return arr != null && arr.length > 0; } // #endregion // #region - isAllElementsNotNull /** * 判断数组的所有元素是否都不为空: *
    *
  1. 数组为 {@code null}:抛出异常,因为传入 {@code null} 通常被视为编程错误。 *
  2. 数组不为 {@code null} 但长度为 0:在这种情况下,通常认为数组中的所有元素都不为 {@code null},因此返回 {@code null}。 *
  3. 数组中有至少一个元素为 {@code null}:返回 {@code false}。 *
  4. 数组中所有元素都不为 {@code null}:返回 {@code true}。 *
* * @param 数组元素的类型 * @param arr 待检查的数组。不为 {@code null} * @return 如果数组的所有元素都不为 {@code null},则返回 {@code true};否则返回 {@code false} * * @throws IllegalArgumentException 当参数为空时抛出 */ public static boolean isAllElementsNotNull(@Nonnull final T[] arr) { AssertTools.checkArgument(arr != null, "The array cannot be null."); for (T element : arr) { if (element == null) { return false; } } return true; } // #endregion // #region - concat /** * 拼接多个数组 * * @param arrays 数组集合,可以为 {@code null} * @return 拼接后的数组 */ public static float[] concatFloatArray(@Nullable Collection arrays) { if (arrays == null || arrays.isEmpty()) { return new float[0]; } final int length = arrays.stream().mapToInt(a -> a.length).sum(); final float[] result = new float[length]; int i = 0; for (float[] arr : arrays) { System.arraycopy(arr, 0, result, i, arr.length); i += arr.length; } return result; } /** * 拼接多个数组 * * @param arrays 数组集合,可以为 {@code null} * @return 拼接后的数组 */ public static double[] concatDoubleArray(@Nullable Collection arrays) { if (arrays == null || arrays.isEmpty()) { return new double[0]; } final int length = arrays.stream().mapToInt(a -> a.length).sum(); final double[] result = new double[length]; int i = 0; for (double[] arr : arrays) { System.arraycopy(arr, 0, result, i, arr.length); i += arr.length; } return result; } /** * 拼接多个数组 * * @param arrays 数组集合,可以为 {@code null} * @return 拼接后的数组 */ public static byte[] concatByteArray(@Nullable Collection arrays) { if (arrays == null || arrays.isEmpty()) { return new byte[0]; } final int length = arrays.stream().mapToInt(a -> a.length).sum(); final byte[] result = new byte[length]; int i = 0; for (byte[] arr : arrays) { System.arraycopy(arr, 0, result, i, arr.length); i += arr.length; } return result; } /** * 拼接多个数组 * * @param arrays 数组集合,可以为 {@code null} * @return 拼接后的数组 */ public static long[] concatLongArray(@Nullable Collection arrays) { if (arrays == null || arrays.isEmpty()) { return new long[0]; } final int length = arrays.stream().mapToInt(a -> a.length).sum(); final long[] result = new long[length]; int i = 0; for (long[] arr : arrays) { System.arraycopy(arr, 0, result, i, arr.length); i += arr.length; } return result; } /** * 拼接多个数组 * * @param arrays 数组集合,可以为 {@code null} * @return 拼接后的数组 */ public static int[] concatIntArray(@Nullable Collection arrays) { if (arrays == null || arrays.isEmpty()) { return new int[0]; } final int length = arrays.stream().mapToInt(a -> a.length).sum(); final int[] result = new int[length]; int i = 0; for (int[] arr : arrays) { System.arraycopy(arr, 0, result, i, arr.length); i += arr.length; } return result; } /** * 将集合中的数组连接为一个列表 * * @param arrays 可能包含多个数组的集合,这些数组中的元素将被连接到一个列表中 * @param 泛型参数,表示数组的元素类型 * @return 返回连接后的列表,如果输入的集合为空或包含空数组,则返回空列表 */ public static List concatToList(@Nullable Collection arrays) { // 如果输入的集合是否为空,则直接返回一个空列表 if (arrays == null || arrays.isEmpty()) { return Collections.emptyList(); } // 计算所有数组的总长度,用于初始化列表的容量 final int length = arrays.stream().mapToInt(a -> a.length).sum(); final List result = new ArrayList<>(length); for (T[] arr : arrays) { Collections.addAll(result, arr); } // 返回连接后的列表 return result; } // #endregion // #region - fill // fill - char public static void fill(char[] a, char... values) { fill(a, 0, a.length, values); } public static void fill(char[] a, String values) { fill(a, 0, a.length, values != null ? values.toCharArray() : EMPTY_CHAR_ARRAY); } public static void fill(char[] a, int fromIndex, int toIndex, char... values) { AssertTools.checkArgumentNotNull(a); if (values.length == 0) { return; } final int start = Integer.max(fromIndex, 0); final int end = Integer.min(toIndex, a.length); if (start >= end) { return; } for (int i = start; i < end; i += values.length) { for (int j = 0; j < values.length; j++) { final int k = (i + j); if (k < end) { a[k] = values[j]; } else { break; } } } } // fill - long public static void fill(long[] a, long... values) { fill(a, 0, a.length, values); } public static void fill(long[] a, int fromIndex, int toIndex, long... values) { AssertTools.checkArgumentNotNull(a); if (values.length == 0) { return; } final int start = Integer.max(fromIndex, 0); final int end = Integer.min(toIndex, a.length); if (start >= end) { return; } for (int i = start; i < end; i += values.length) { for (int j = 0; j < values.length; j++) { final int k = (i + j); if (k < end) { a[k] = values[j]; } else { break; } } } } // fill - float public static void fill(float[] a, float... values) { fill(a, 0, a.length, values); } public static void fill(float[] a, int fromIndex, int toIndex, float... values) { AssertTools.checkArgumentNotNull(a); if (values.length == 0) { return; } final int start = Integer.max(fromIndex, 0); final int end = Integer.min(toIndex, a.length); if (start >= end) { return; } for (int i = start; i < end; i += values.length) { for (int j = 0; j < values.length; j++) { final int k = (i + j); if (k < end) { a[k] = values[j]; } else { break; } } } } // fill - double public static void fill(double[] a, double... values) { fill(a, 0, a.length, values); } public static void fill(double[] a, int fromIndex, int toIndex, double... values) { AssertTools.checkArgumentNotNull(a); if (values.length == 0) { return; } final int start = Integer.max(fromIndex, 0); final int end = Integer.min(toIndex, a.length); if (start >= end) { return; } for (int i = start; i < end; i += values.length) { for (int j = 0; j < values.length; j++) { final int k = (i + j); if (k < end) { a[k] = values[j]; } else { break; } } } } // fill - T public static void fill(@Nonnull T[] a, T[] values) { fillInternal(a, 0, a.length, values); } public static void fill(@Nonnull T[] a, int fromIndex, int toIndex, T[] values) { fillInternal(a, fromIndex, toIndex, values); } private static void fillInternal(@Nonnull T[] a, int fromIndex, int toIndex, @Nullable T[] values) { AssertTools.checkArgumentNotNull(a); if (values == null || values.length == 0) { return; } final int start = Integer.max(fromIndex, 0); final int end = Integer.min(toIndex, a.length); if (start >= end) { return; } for (int i = start; i < end; i += values.length) { for (int j = 0; j < values.length; j++) { final int k = (i + j); if (k < end) { a[k] = values[j]; } else { break; } } } } // #endregion // #region - private constructor private ArrayTools() { throw new IllegalStateException("Utility class"); } // #endregion }