package edu.washington.escience.myria.util; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.stream.IntStream; import org.slf4j.LoggerFactory; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.primitives.Ints; /** * Array related utility functions. */ public final class MyriaArrayUtils extends org.apache.commons.lang3.ArrayUtils { /** The logger for this class. */ protected static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(MyriaArrayUtils.class); /** * Utility classes should not be instantiated. */ private MyriaArrayUtils() {} /** * Fill object array. * * @return the filled array. * @param arr the array to fill * @param e the element to fill. */ public static Object[] arrayFillAndReturn(final Object[] arr, final Object e) { Arrays.fill(arr, e); return arr; } /** * Fill int array. * * @return the filled array. * @param arr the array to fill * @param e the element to fill. */ public static int[] arrayFillAndReturn(final int[] arr, final int e) { Arrays.fill(arr, e); return arr; } /** * @param n size of 2d index * @return a 2D index like { {0},{1},{2},..., {n-1} } */ public static List<List<Integer>> create2DVerticalIndexList(final int n) { List<List<Integer>> result = new ArrayList<List<Integer>>(); for (int i = 0; i < n; i++) { result.add(Lists.newArrayList(i)); } return result; } /** * @param n size of 2d index * @return a 2D index like { {0,1,2,...,n-1} } */ public static List<List<Integer>> create2DHorizontalIndexList(final int n) { List<List<Integer>> result = new ArrayList<List<Integer>>(); result.add(new ArrayList<Integer>()); for (int i = 0; i < n; i++) { result.get(0).add(i); } return result; } /** * convert a 1D array into a 2D array. * * @param arr input 1D array. * @return 2D array returned. */ public static int[][] get2DArray(final int[] arr) { int[][] result = new int[arr.length][]; for (int i = 0; i < arr.length; i++) { result[i] = new int[] {arr[i]}; } return result; } /** * @param maybeSetArray data array * @return An ImmutableSet of the data array if the data array is actually a set * @throws IllegalArgumentException if the data array is not a set. * @param <E> array element type. */ public static <E> ImmutableSet<E> checkSet(final E[] maybeSetArray) { ImmutableSet.Builder<E> builder = new ImmutableSet.Builder<>(); for (E i : maybeSetArray) { builder.add(i); } ImmutableSet<E> r = builder.build(); if (r.size() != maybeSetArray.length) { throw new IllegalArgumentException( "The array " + Arrays.toString(maybeSetArray) + " is not a set"); } return r; } /** * Check if an array of int is a set. If not, log a warning. * * @param maybeSetArray data array * @return the array itself */ public static int[] warnIfNotSet(final int[] maybeSetArray) { try { return checkSet(maybeSetArray); } catch (IllegalArgumentException e) { LOGGER.warn("Array " + Arrays.toString(maybeSetArray) + " is not a set", e); return maybeSetArray; } } /** * Check if an array of int is a set. * * @param maybeSetArray data array * @return the array it self * @throws IllegalArgumentException if the data array is not a set. */ public static int[] checkSet(final int[] maybeSetArray) { Set<Integer> tmp = Sets.newHashSet(Ints.asList(maybeSetArray)); if (maybeSetArray.length != tmp.size()) { throw new IllegalArgumentException( "The array " + Arrays.toString(maybeSetArray) + " is not a set"); } return maybeSetArray; } /** * Check if an array of int is a list of valid indices of another data array . * * @param arrayOfIndices indices array * @param size the size of another array, i.e. the data array * @return the arrayOfIndices it self * @throws IllegalArgumentException if check fails. */ public static int[] checkPositionIndices(final int[] arrayOfIndices, final int size) { for (int i : arrayOfIndices) { Preconditions.checkPositionIndex(i, size); } return arrayOfIndices; } /** * Helper function that generates an array of the numbers in [start, start+length). * * @param start the size of the array. * @param length the length of the array. * @return an array of the numbers [start, start+length). */ public static int[] range(final int start, final int length) { return IntStream.range(start, start + length).toArray(); } }