All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.helger.commons.collection.ArrayHelper Maven / Gradle / Ivy

There is a newer version: 11.1.10
Show newest version
/*
 * Copyright (C) 2014-2022 Philip Helger (www.helger.com)
 * philip[at]helger[dot]com
 *
 * 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
 *
 *         http://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 com.helger.commons.collection;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import com.helger.commons.CGlobal;
import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.PresentForCodeCoverage;
import com.helger.commons.annotation.ReturnsMutableCopy;
import com.helger.commons.annotation.ReturnsMutableObject;
import com.helger.commons.equals.EqualsHelper;
import com.helger.commons.lang.ClassHelper;
import com.helger.commons.lang.GenericReflection;

/**
 * Provides additional helper methods for array handling.
 *
 * @author Philip Helger
 */
@Immutable
public final class ArrayHelper
{
  /** Constant empty boolean array */
  public static final boolean [] EMPTY_BOOLEAN_ARRAY = new boolean [0];
  /** Constant empty byte array */
  public static final byte [] EMPTY_BYTE_ARRAY = new byte [0];
  /** Constant empty char array */
  public static final char [] EMPTY_CHAR_ARRAY = new char [0];
  /** Constant empty double array */
  public static final double [] EMPTY_DOUBLE_ARRAY = new double [0];
  /** Constant empty float array */
  public static final float [] EMPTY_FLOAT_ARRAY = new float [0];
  /** Constant empty int array */
  public static final int [] EMPTY_INT_ARRAY = new int [0];
  /** Constant empty long array */
  public static final long [] EMPTY_LONG_ARRAY = new long [0];
  /** Constant empty short array */
  public static final short [] EMPTY_SHORT_ARRAY = new short [0];
  /** Constant empty boolean array */
  public static final Boolean [] EMPTY_BOOLEAN_OBJ_ARRAY = new Boolean [0];
  /** Constant empty byte array */
  public static final Byte [] EMPTY_BYTE_OBJ_ARRAY = new Byte [0];
  /** Constant empty char array */
  public static final Character [] EMPTY_CHAR_OBJ_ARRAY = new Character [0];
  /** Constant empty double array */
  public static final Double [] EMPTY_DOUBLE_OBJ_ARRAY = new Double [0];
  /** Constant empty float array */
  public static final Float [] EMPTY_FLOAT_OBJ_ARRAY = new Float [0];
  /** Constant empty int array */
  public static final Integer [] EMPTY_INT_OBJ_ARRAY = new Integer [0];
  /** Constant empty long array */
  public static final Long [] EMPTY_LONG_OBJ_ARRAY = new Long [0];
  /** Constant empty short array */
  public static final Short [] EMPTY_SHORT_OBJ_ARRAY = new Short [0];
  /** Constant empty Object array */
  public static final Object [] EMPTY_OBJECT_ARRAY = new Object [0];
  /** Constant empty String array */
  public static final String [] EMPTY_STRING_ARRAY = new String [0];
  /** Constant empty Class<?> array */
  public static final Class  [] EMPTY_CLASS_ARRAY = new Class  [0];

  @PresentForCodeCoverage
  private static final ArrayHelper INSTANCE = new ArrayHelper ();

  private ArrayHelper ()
  {}

  /**
   * Get the component type of the array (the type of which the array is made
   * up)
   *
   * @param 
   *        The component type of the array
   * @param aArray
   *        The array to get the type from. May not be null.
   * @return The class that determines a single element of the array.
   */
  @Nonnull
  public static  Class  getComponentType (@Nonnull final ELEMENTTYPE [] aArray)
  {
    ValueEnforcer.notNull (aArray, "Array");
    final Class  aComponentType = aArray.getClass ().getComponentType ();
    return GenericReflection.uncheckedCast (aComponentType);
  }

  /**
   * Check if the passed object is an array or not.
   *
   * @param aObject
   *        The object to be checked. May be null.
   * @return true if the passed object is not null and
   *         represents an array.
   */
  public static boolean isArray (@Nullable final Object aObject)
  {
    return aObject != null && ClassHelper.isArrayClass (aObject.getClass ());
  }

  /**
   * @param aArray
   *        The array who's size is to be queried. May be null.
   * @return 0 if the passed array is null - it's length otherwise.
   */
  @Nonnegative
  public static int getSize (@Nullable final boolean... aArray)
  {
    return aArray == null ? 0 : aArray.length;
  }

  /**
   * @param aArray
   *        The array who's size is to be queried. May be null.
   * @return 0 if the passed array is null - it's length otherwise.
   */
  @Nonnegative
  public static int getSize (@Nullable final byte... aArray)
  {
    return aArray == null ? 0 : aArray.length;
  }

  /**
   * @param aArray
   *        The array who's size is to be queried. May be null.
   * @return 0 if the passed array is null - it's length otherwise.
   */
  @Nonnegative
  public static int getSize (@Nullable final char... aArray)
  {
    return aArray == null ? 0 : aArray.length;
  }

  /**
   * @param aArray
   *        The array who's size is to be queried. May be null.
   * @return 0 if the passed array is null - it's length otherwise.
   */
  @Nonnegative
  public static int getSize (@Nullable final double... aArray)
  {
    return aArray == null ? 0 : aArray.length;
  }

  /**
   * @param aArray
   *        The array who's size is to be queried. May be null.
   * @return 0 if the passed array is null - it's length otherwise.
   */
  @Nonnegative
  public static int getSize (@Nullable final float... aArray)
  {
    return aArray == null ? 0 : aArray.length;
  }

  /**
   * @param aArray
   *        The array who's size is to be queried. May be null.
   * @return 0 if the passed array is null - it's length otherwise.
   */
  @Nonnegative
  public static int getSize (@Nullable final int... aArray)
  {
    return aArray == null ? 0 : aArray.length;
  }

  /**
   * @param aArray
   *        The array who's size is to be queried. May be null.
   * @return 0 if the passed array is null - it's length otherwise.
   */
  @Nonnegative
  public static int getSize (@Nullable final long... aArray)
  {
    return aArray == null ? 0 : aArray.length;
  }

  /**
   * @param aArray
   *        The array who's size is to be queried. May be null.
   * @return 0 if the passed array is null - it's length otherwise.
   */
  @Nonnegative
  public static int getSize (@Nullable final short... aArray)
  {
    return aArray == null ? 0 : aArray.length;
  }

  /**
   * @param 
   *        Array element type
   * @param aArray
   *        The array who's size is to be queried. May be null.
   * @return 0 if the passed array is null - it's length otherwise.
   */
  @Nonnegative
  @SafeVarargs
  public static  int getSize (@Nullable final ELEMENTTYPE... aArray)
  {
    return aArray == null ? 0 : aArray.length;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return true if the passed array is null or
   *         empty.
   */
  public static boolean isEmpty (@Nullable final boolean... aArray)
  {
    return getSize (aArray) == 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return true if the passed array is null or
   *         empty.
   */
  public static boolean isEmpty (@Nullable final byte... aArray)
  {
    return getSize (aArray) == 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return true if the passed array is null or
   *         empty.
   */
  public static boolean isEmpty (@Nullable final char... aArray)
  {
    return getSize (aArray) == 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return true if the passed array is null or
   *         empty.
   */
  public static boolean isEmpty (@Nullable final double... aArray)
  {
    return getSize (aArray) == 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return true if the passed array is null or
   *         empty.
   */
  public static boolean isEmpty (@Nullable final float... aArray)
  {
    return getSize (aArray) == 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return true if the passed array is null or
   *         empty.
   */
  public static boolean isEmpty (@Nullable final int... aArray)
  {
    return getSize (aArray) == 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return true if the passed array is null or
   *         empty.
   */
  public static boolean isEmpty (@Nullable final long... aArray)
  {
    return getSize (aArray) == 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return true if the passed array is null or
   *         empty.
   */
  public static boolean isEmpty (@Nullable final short... aArray)
  {
    return getSize (aArray) == 0;
  }

  /**
   * @param 
   *        Array element type
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return true if the passed array is null or
   *         empty.
   */
  @SafeVarargs
  public static  boolean isEmpty (@Nullable final ELEMENTTYPE... aArray)
  {
    return getSize (aArray) == 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return false if the passed array is null or
   *         empty.
   */
  public static boolean isNotEmpty (@Nullable final boolean... aArray)
  {
    return getSize (aArray) > 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return false if the passed array is null or
   *         empty.
   */
  public static boolean isNotEmpty (@Nullable final byte... aArray)
  {
    return getSize (aArray) > 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return false if the passed array is null or
   *         empty.
   */
  public static boolean isNotEmpty (@Nullable final char... aArray)
  {
    return getSize (aArray) > 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return false if the passed array is null or
   *         empty.
   */
  public static boolean isNotEmpty (@Nullable final double... aArray)
  {
    return getSize (aArray) > 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return false if the passed array is null or
   *         empty.
   */
  public static boolean isNotEmpty (@Nullable final float... aArray)
  {
    return getSize (aArray) > 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return false if the passed array is null or
   *         empty.
   */
  public static boolean isNotEmpty (@Nullable final int... aArray)
  {
    return getSize (aArray) > 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return false if the passed array is null or
   *         empty.
   */
  public static boolean isNotEmpty (@Nullable final long... aArray)
  {
    return getSize (aArray) > 0;
  }

  /**
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return false if the passed array is null or
   *         empty.
   */
  public static boolean isNotEmpty (@Nullable final short... aArray)
  {
    return getSize (aArray) > 0;
  }

  /**
   * @param 
   *        Array element type
   * @param aArray
   *        The array to be queried if it is empty. May be null.
   * @return false if the passed array is null or
   *         empty.
   */
  @SafeVarargs
  public static  boolean isNotEmpty (@Nullable final ELEMENTTYPE... aArray)
  {
    return getSize (aArray) > 0;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param 
   *        Array element type
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static  int getFirstIndex (@Nullable final ELEMENTTYPE [] aValues, @Nullable final ELEMENTTYPE aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = 0; nIndex < nLength; ++nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getFirstIndex (@Nullable final boolean [] aValues, final boolean aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = 0; nIndex < nLength; ++nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getFirstIndex (@Nullable final byte [] aValues, final byte aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = 0; nIndex < nLength; ++nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getFirstIndex (@Nullable final char [] aValues, final char aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = 0; nIndex < nLength; ++nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getFirstIndex (@Nullable final double [] aValues, final double aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = 0; nIndex < nLength; ++nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getFirstIndex (@Nullable final float [] aValues, final float aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = 0; nIndex < nLength; ++nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getFirstIndex (@Nullable final int [] aValues, final int aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = 0; nIndex < nLength; ++nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getFirstIndex (@Nullable final long [] aValues, final long aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = 0; nIndex < nLength; ++nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getFirstIndex (@Nullable final short [] aValues, final short aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = 0; nIndex < nLength; ++nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param 
   *        Array element type
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static  int getLastIndex (@Nullable final ELEMENTTYPE [] aValues, @Nullable final ELEMENTTYPE aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = nLength - 1; nIndex >= 0; --nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getLastIndex (@Nullable final boolean [] aValues, final boolean aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = nLength - 1; nIndex >= 0; --nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getLastIndex (@Nullable final byte [] aValues, final byte aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = nLength - 1; nIndex >= 0; --nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getLastIndex (@Nullable final char [] aValues, final char aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = nLength - 1; nIndex >= 0; --nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getLastIndex (@Nullable final double [] aValues, final double aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = nLength - 1; nIndex >= 0; --nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getLastIndex (@Nullable final float [] aValues, final float aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = nLength - 1; nIndex >= 0; --nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getLastIndex (@Nullable final int [] aValues, final int aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = nLength - 1; nIndex >= 0; --nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getLastIndex (@Nullable final long [] aValues, final long aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = nLength - 1; nIndex >= 0; --nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Get the index of the passed search value in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return -1 if the searched value is not contained, a value
   *         ≥ 0 otherwise.
   */
  public static int getLastIndex (@Nullable final short [] aValues, final short aSearchValue)
  {
    final int nLength = getSize (aValues);
    if (nLength > 0)
      for (int nIndex = nLength - 1; nIndex >= 0; --nIndex)
        if (EqualsHelper.equals (aValues[nIndex], aSearchValue))
          return nIndex;
    return CGlobal.ILLEGAL_UINT;
  }

  /**
   * Check if the passed search value is contained in the passed value array.
   *
   * @param 
   *        Array element type
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return true if the value array is not empty and the search
   *         value is contained - false otherwise.
   */
  public static  boolean contains (@Nullable final ELEMENTTYPE [] aValues, @Nullable final ELEMENTTYPE aSearchValue)
  {
    return getFirstIndex (aValues, aSearchValue) >= 0;
  }

  /**
   * Check if the passed search value is contained in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return true if the value array is not empty and the search
   *         value is contained - false otherwise.
   */
  public static boolean contains (@Nullable final boolean [] aValues, final boolean aSearchValue)
  {
    return getFirstIndex (aValues, aSearchValue) >= 0;
  }

  /**
   * Check if the passed search value is contained in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return true if the value array is not empty and the search
   *         value is contained - false otherwise.
   */
  public static boolean contains (@Nullable final byte [] aValues, final byte aSearchValue)
  {
    return getFirstIndex (aValues, aSearchValue) >= 0;
  }

  /**
   * Check if the passed search value is contained in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return true if the value array is not empty and the search
   *         value is contained - false otherwise.
   */
  public static boolean contains (@Nullable final char [] aValues, final char aSearchValue)
  {
    return getFirstIndex (aValues, aSearchValue) >= 0;
  }

  /**
   * Check if the passed search value is contained in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return true if the value array is not empty and the search
   *         value is contained - false otherwise.
   */
  public static boolean contains (@Nullable final double [] aValues, final double aSearchValue)
  {
    return getFirstIndex (aValues, aSearchValue) >= 0;
  }

  /**
   * Check if the passed search value is contained in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return true if the value array is not empty and the search
   *         value is contained - false otherwise.
   */
  public static boolean contains (@Nullable final float [] aValues, final float aSearchValue)
  {
    return getFirstIndex (aValues, aSearchValue) >= 0;
  }

  /**
   * Check if the passed search value is contained in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return true if the value array is not empty and the search
   *         value is contained - false otherwise.
   */
  public static boolean contains (@Nullable final int [] aValues, final int aSearchValue)
  {
    return getFirstIndex (aValues, aSearchValue) >= 0;
  }

  /**
   * Check if the passed search value is contained in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return true if the value array is not empty and the search
   *         value is contained - false otherwise.
   */
  public static boolean contains (@Nullable final long [] aValues, final long aSearchValue)
  {
    return getFirstIndex (aValues, aSearchValue) >= 0;
  }

  /**
   * Check if the passed search value is contained in the passed value array.
   *
   * @param aValues
   *        The value array to be searched. May be null.
   * @param aSearchValue
   *        The value to be searched. May be null.
   * @return true if the value array is not empty and the search
   *         value is contained - false otherwise.
   */
  public static boolean contains (@Nullable final short [] aValues, final short aSearchValue)
  {
    return getFirstIndex (aValues, aSearchValue) >= 0;
  }

  /**
   * Get the first element of the array or the passed default if the passed
   * array is empty.
   *
   * @param aArray
   *        The array who's first element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the first element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static boolean getFirst (@Nullable final boolean [] aArray, final boolean aDefaultValue)
  {
    return isEmpty (aArray) ? aDefaultValue : aArray[0];
  }

  /**
   * Get the first element of the array or the passed default if the passed
   * array is empty.
   *
   * @param aArray
   *        The array who's first element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the first element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static byte getFirst (@Nullable final byte [] aArray, final byte aDefaultValue)
  {
    return isEmpty (aArray) ? aDefaultValue : aArray[0];
  }

  /**
   * Get the first element of the array or the passed default if the passed
   * array is empty.
   *
   * @param aArray
   *        The array who's first element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the first element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static char getFirst (@Nullable final char [] aArray, final char aDefaultValue)
  {
    return isEmpty (aArray) ? aDefaultValue : aArray[0];
  }

  /**
   * Get the first element of the array or the passed default if the passed
   * array is empty.
   *
   * @param aArray
   *        The array who's first element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the first element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static double getFirst (@Nullable final double [] aArray, final double aDefaultValue)
  {
    return isEmpty (aArray) ? aDefaultValue : aArray[0];
  }

  /**
   * Get the first element of the array or the passed default if the passed
   * array is empty.
   *
   * @param aArray
   *        The array who's first element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the first element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static float getFirst (@Nullable final float [] aArray, final float aDefaultValue)
  {
    return isEmpty (aArray) ? aDefaultValue : aArray[0];
  }

  /**
   * Get the first element of the array or the passed default if the passed
   * array is empty.
   *
   * @param aArray
   *        The array who's first element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the first element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static int getFirst (@Nullable final int [] aArray, final int aDefaultValue)
  {
    return isEmpty (aArray) ? aDefaultValue : aArray[0];
  }

  /**
   * Get the first element of the array or the passed default if the passed
   * array is empty.
   *
   * @param aArray
   *        The array who's first element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the first element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static long getFirst (@Nullable final long [] aArray, final long aDefaultValue)
  {
    return isEmpty (aArray) ? aDefaultValue : aArray[0];
  }

  /**
   * Get the first element of the array or the passed default if the passed
   * array is empty.
   *
   * @param aArray
   *        The array who's first element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the first element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static short getFirst (@Nullable final short [] aArray, final short aDefaultValue)
  {
    return isEmpty (aArray) ? aDefaultValue : aArray[0];
  }

  /**
   * Get the first element of the array or null if the passed array
   * is empty.
   *
   * @param 
   *        Array element type
   * @param aArray
   *        The array who's first element is to be retrieved. May be
   *        null or empty.
   * @return null if the passed array is null or empty
   *         - the first element otherwise (may also be null).
   */
  @Nullable
  @SafeVarargs
  public static  ELEMENTTYPE getFirst (@Nullable final ELEMENTTYPE... aArray)
  {
    return getFirst (aArray, null);
  }

  /**
   * Get the first element of the array or the passed default if the passed
   * array is empty.
   *
   * @param 
   *        Array element type
   * @param aArray
   *        The array who's first element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the first element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  @Nullable
  public static  ELEMENTTYPE getFirst (@Nullable final ELEMENTTYPE [] aArray, @Nullable final ELEMENTTYPE aDefaultValue)
  {
    return isEmpty (aArray) ? aDefaultValue : aArray[0];
  }

  /**
   * Get the last element of the array or the passed default if the passed array
   * is empty.
   *
   * @param aArray
   *        The array who's last element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the last element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static boolean getLast (@Nullable final boolean [] aArray, final boolean aDefaultValue)
  {
    final int nSize = getSize (aArray);
    return nSize == 0 ? aDefaultValue : aArray[nSize - 1];
  }

  /**
   * Get the last element of the array or the passed default if the passed array
   * is empty.
   *
   * @param aArray
   *        The array who's last element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the last element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static byte getLast (@Nullable final byte [] aArray, final byte aDefaultValue)
  {
    final int nSize = getSize (aArray);
    return nSize == 0 ? aDefaultValue : aArray[nSize - 1];
  }

  /**
   * Get the last element of the array or the passed default if the passed array
   * is empty.
   *
   * @param aArray
   *        The array who's last element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the last element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static char getLast (@Nullable final char [] aArray, final char aDefaultValue)
  {
    final int nSize = getSize (aArray);
    return nSize == 0 ? aDefaultValue : aArray[nSize - 1];
  }

  /**
   * Get the last element of the array or the passed default if the passed array
   * is empty.
   *
   * @param aArray
   *        The array who's last element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the last element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static double getLast (@Nullable final double [] aArray, final double aDefaultValue)
  {
    final int nSize = getSize (aArray);
    return nSize == 0 ? aDefaultValue : aArray[nSize - 1];
  }

  /**
   * Get the last element of the array or the passed default if the passed array
   * is empty.
   *
   * @param aArray
   *        The array who's last element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the last element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static float getLast (@Nullable final float [] aArray, final float aDefaultValue)
  {
    final int nSize = getSize (aArray);
    return nSize == 0 ? aDefaultValue : aArray[nSize - 1];
  }

  /**
   * Get the last element of the array or the passed default if the passed array
   * is empty.
   *
   * @param aArray
   *        The array who's last element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the last element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static int getLast (@Nullable final int [] aArray, final int aDefaultValue)
  {
    final int nSize = getSize (aArray);
    return nSize == 0 ? aDefaultValue : aArray[nSize - 1];
  }

  /**
   * Get the last element of the array or the passed default if the passed array
   * is empty.
   *
   * @param aArray
   *        The array who's last element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the last element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static long getLast (@Nullable final long [] aArray, final long aDefaultValue)
  {
    final int nSize = getSize (aArray);
    return nSize == 0 ? aDefaultValue : aArray[nSize - 1];
  }

  /**
   * Get the last element of the array or the passed default if the passed array
   * is empty.
   *
   * @param aArray
   *        The array who's last element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the last element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  public static short getLast (@Nullable final short [] aArray, final short aDefaultValue)
  {
    final int nSize = getSize (aArray);
    return nSize == 0 ? aDefaultValue : aArray[nSize - 1];
  }

  /**
   * Get the last element of the array or null if the passed array
   * is empty.
   *
   * @param 
   *        Array element type
   * @param aArray
   *        The array who's last element is to be retrieved. May be
   *        null or empty.
   * @return null if the passed array is null or empty
   *         - the last element otherwise (may also be null).
   */
  @Nullable
  @SafeVarargs
  public static  ELEMENTTYPE getLast (@Nullable final ELEMENTTYPE... aArray)
  {
    return getLast (aArray, null);
  }

  /**
   * Get the last element of the array or the passed default if the passed array
   * is empty.
   *
   * @param 
   *        Array element type
   * @param aArray
   *        The array who's last element is to be retrieved. May be
   *        null or empty.
   * @param aDefaultValue
   *        The default value to be returned if the array is empty
   * @return the last element if the passed array is not empty, the default
   *         value if the passed array is empty.
   */
  @Nullable
  public static  ELEMENTTYPE getLast (@Nullable final ELEMENTTYPE [] aArray, @Nullable final ELEMENTTYPE aDefaultValue)
  {
    final int nSize = getSize (aArray);
    return nSize == 0 ? aDefaultValue : aArray[nSize - 1];
  }

  /**
   * Get a 1:1 copy of the passed array. Nested elements are not deep-copied -
   * the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static boolean [] getCopy (@Nullable final boolean... aArray)
  {
    return aArray == null ? null : getCopy (aArray, 0, aArray.length);
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements. Nested elements are not deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, only the available number of elements in the
   *        source array are copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static boolean [] getCopy (@Nullable final boolean [] aArray, @Nonnegative final int nLength)
  {
    return aArray == null ? null : getCopy (aArray, 0, Math.min (aArray.length, nLength));
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements starting at the specified index. Nested elements are not
   * deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nStartIndex
   *        The index where the copying should start. Must be >= 0!
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, an exception is thrown.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   * @see System#arraycopy(Object, int, Object, int, int)
   */
  @Nullable
  @ReturnsMutableCopy
  public static boolean [] getCopy (@Nullable final boolean [] aArray, @Nonnegative final int nStartIndex, @Nonnegative final int nLength)
  {
    if (aArray == null)
      return null;
    final boolean [] ret = new boolean [nLength];
    System.arraycopy (aArray, nStartIndex, ret, 0, nLength);
    return ret;
  }

  /**
   * Get a 1:1 copy of the passed array. Nested elements are not deep-copied -
   * the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static byte [] getCopy (@Nullable final byte... aArray)
  {
    return aArray == null ? null : getCopy (aArray, 0, aArray.length);
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements. Nested elements are not deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, only the available number of elements in the
   *        source array are copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static byte [] getCopy (@Nullable final byte [] aArray, @Nonnegative final int nLength)
  {
    return aArray == null ? null : getCopy (aArray, 0, Math.min (aArray.length, nLength));
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements starting at the specified index. Nested elements are not
   * deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nStartIndex
   *        The index where the copying should start. Must be >= 0!
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, an exception is thrown.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   * @see System#arraycopy(Object, int, Object, int, int)
   */
  @Nullable
  @ReturnsMutableCopy
  public static byte [] getCopy (@Nullable final byte [] aArray, @Nonnegative final int nStartIndex, @Nonnegative final int nLength)
  {
    if (aArray == null)
      return null;
    final byte [] ret = new byte [nLength];
    System.arraycopy (aArray, nStartIndex, ret, 0, nLength);
    return ret;
  }

  /**
   * Get a 1:1 copy of the passed array. Nested elements are not deep-copied -
   * the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static char [] getCopy (@Nullable final char... aArray)
  {
    return aArray == null ? null : getCopy (aArray, 0, aArray.length);
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements. Nested elements are not deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, only the available number of elements in the
   *        source array are copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static char [] getCopy (@Nullable final char [] aArray, @Nonnegative final int nLength)
  {
    return aArray == null ? null : getCopy (aArray, 0, Math.min (aArray.length, nLength));
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements starting at the specified index. Nested elements are not
   * deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nStartIndex
   *        The index where the copying should start. Must be >= 0!
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, an exception is thrown.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   * @see System#arraycopy(Object, int, Object, int, int)
   */
  @Nullable
  @ReturnsMutableCopy
  public static char [] getCopy (@Nullable final char [] aArray, @Nonnegative final int nStartIndex, @Nonnegative final int nLength)
  {
    if (aArray == null)
      return null;
    final char [] ret = new char [nLength];
    System.arraycopy (aArray, nStartIndex, ret, 0, nLength);
    return ret;
  }

  /**
   * Get a 1:1 copy of the passed array. Nested elements are not deep-copied -
   * the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static double [] getCopy (@Nullable final double... aArray)
  {
    return aArray == null ? null : getCopy (aArray, 0, aArray.length);
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements. Nested elements are not deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, only the available number of elements in the
   *        source array are copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static double [] getCopy (@Nullable final double [] aArray, @Nonnegative final int nLength)
  {
    return aArray == null ? null : getCopy (aArray, 0, Math.min (aArray.length, nLength));
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements starting at the specified index. Nested elements are not
   * deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nStartIndex
   *        The index where the copying should start. Must be >= 0!
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, an exception is thrown.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   * @see System#arraycopy(Object, int, Object, int, int)
   */
  @Nullable
  @ReturnsMutableCopy
  public static double [] getCopy (@Nullable final double [] aArray, @Nonnegative final int nStartIndex, @Nonnegative final int nLength)
  {
    if (aArray == null)
      return null;
    final double [] ret = new double [nLength];
    System.arraycopy (aArray, nStartIndex, ret, 0, nLength);
    return ret;
  }

  /**
   * Get a 1:1 copy of the passed array. Nested elements are not deep-copied -
   * the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static float [] getCopy (@Nullable final float... aArray)
  {
    return aArray == null ? null : getCopy (aArray, 0, aArray.length);
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements. Nested elements are not deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, only the available number of elements in the
   *        source array are copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static float [] getCopy (@Nullable final float [] aArray, @Nonnegative final int nLength)
  {
    return aArray == null ? null : getCopy (aArray, 0, Math.min (aArray.length, nLength));
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements starting at the specified index. Nested elements are not
   * deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nStartIndex
   *        The index where the copying should start. Must be >= 0!
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, an exception is thrown.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   * @see System#arraycopy(Object, int, Object, int, int)
   */
  @Nullable
  @ReturnsMutableCopy
  public static float [] getCopy (@Nullable final float [] aArray, @Nonnegative final int nStartIndex, @Nonnegative final int nLength)
  {
    if (aArray == null)
      return null;
    final float [] ret = new float [nLength];
    System.arraycopy (aArray, nStartIndex, ret, 0, nLength);
    return ret;
  }

  /**
   * Get a 1:1 copy of the passed array. Nested elements are not deep-copied -
   * the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */

  @Nullable
  @ReturnsMutableCopy
  public static int [] getCopy (@Nullable final int... aArray)
  {
    return aArray == null ? null : getCopy (aArray, 0, aArray.length);
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements. Nested elements are not deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, only the available number of elements in the
   *        source array are copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static int [] getCopy (@Nullable final int [] aArray, @Nonnegative final int nLength)
  {
    return aArray == null ? null : getCopy (aArray, 0, Math.min (aArray.length, nLength));
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements starting at the specified index. Nested elements are not
   * deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nStartIndex
   *        The index where the copying should start. Must be >= 0!
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, an exception is thrown.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   * @see System#arraycopy(Object, int, Object, int, int)
   */
  /**
   * Get a 1:1 copy of the passed array. Nested elements are not deep-copied -
   * the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nStartIndex
   *        The index where the copying should start. Must be >= 0!
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, an exception is thrown.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static int [] getCopy (@Nullable final int [] aArray, @Nonnegative final int nStartIndex, @Nonnegative final int nLength)
  {
    if (aArray == null)
      return null;
    final int [] ret = new int [nLength];
    System.arraycopy (aArray, nStartIndex, ret, 0, nLength);
    return ret;
  }

  @Nullable
  @ReturnsMutableCopy
  public static long [] getCopy (@Nullable final long... aArray)
  {
    return aArray == null ? null : getCopy (aArray, 0, aArray.length);
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements. Nested elements are not deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, only the available number of elements in the
   *        source array are copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static long [] getCopy (@Nullable final long [] aArray, @Nonnegative final int nLength)
  {
    return aArray == null ? null : getCopy (aArray, 0, Math.min (aArray.length, nLength));
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements starting at the specified index. Nested elements are not
   * deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nStartIndex
   *        The index where the copying should start. Must be >= 0!
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, an exception is thrown.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   * @see System#arraycopy(Object, int, Object, int, int)
   */
  @Nullable
  @ReturnsMutableCopy
  public static long [] getCopy (@Nullable final long [] aArray, @Nonnegative final int nStartIndex, @Nonnegative final int nLength)
  {
    if (aArray == null)
      return null;
    final long [] ret = new long [nLength];
    System.arraycopy (aArray, nStartIndex, ret, 0, nLength);
    return ret;
  }

  /**
   * Get a 1:1 copy of the passed array. Nested elements are not deep-copied -
   * the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static short [] getCopy (@Nullable final short... aArray)
  {
    return aArray == null ? null : getCopy (aArray, 0, aArray.length);
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements. Nested elements are not deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, only the available number of elements in the
   *        source array are copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static short [] getCopy (@Nullable final short [] aArray, @Nonnegative final int nLength)
  {
    return aArray == null ? null : getCopy (aArray, 0, Math.min (aArray.length, nLength));
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements starting at the specified index. Nested elements are not
   * deep-copied - the references are re-used!
   *
   * @param aArray
   *        The array to be copied.
   * @param nStartIndex
   *        The index where the copying should start. Must be >= 0!
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, an exception is thrown.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   * @see System#arraycopy(Object, int, Object, int, int)
   */
  @Nullable
  @ReturnsMutableCopy
  public static short [] getCopy (@Nullable final short [] aArray, @Nonnegative final int nStartIndex, @Nonnegative final int nLength)
  {
    if (aArray == null)
      return null;
    final short [] ret = new short [nLength];
    System.arraycopy (aArray, nStartIndex, ret, 0, nLength);
    return ret;
  }

  /**
   * Get a 1:1 copy of the passed array. Nested elements are not deep-copied -
   * the references are re-used!
   *
   * @param 
   *        Array element type
   * @param aArray
   *        The array to be copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  @SafeVarargs
  public static  ELEMENTTYPE [] getCopy (@Nullable final ELEMENTTYPE... aArray)
  {
    return aArray == null ? null : getCopy (aArray, 0, aArray.length);
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements. Nested elements are not deep-copied - the references are re-used!
   *
   * @param 
   *        Array element type
   * @param aArray
   *        The array to be copied.
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, only the available number of elements in the
   *        source array are copied.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static  ELEMENTTYPE [] getCopy (@Nullable final ELEMENTTYPE [] aArray, @Nonnegative final int nLength)
  {
    return aArray == null ? null : getCopy (aArray, 0, Math.min (aArray.length, nLength));
  }

  /**
   * Get a 1:1 copy of the passed array using the passed number of array
   * elements starting at the specified index. Nested elements are not
   * deep-copied - the references are re-used!
   *
   * @param 
   *        Array element type
   * @param aArray
   *        The array to be copied.
   * @param nStartIndex
   *        The index where the copying should start. Must be >= 0!
   * @param nLength
   *        The number of elements to be copied into the new array. May not be
   *        < 0. If the passed number of elements exceeds the number of
   *        elements in the array, an exception is thrown.
   * @return null if the passed array is null - a non-
   *         null copy otherwise.
   * @see System#arraycopy(Object, int, Object, int, int)
   */
  @Nullable
  @ReturnsMutableCopy
  public static  ELEMENTTYPE [] getCopy (@Nullable final ELEMENTTYPE [] aArray,
                                                      @Nonnegative final int nStartIndex,
                                                      @Nonnegative final int nLength)
  {
    if (aArray == null)
      return null;
    final ELEMENTTYPE [] ret = newArraySameType (aArray, nLength);
    System.arraycopy (aArray, nStartIndex, ret, 0, nLength);
    return ret;
  }

  /**
   * Get a new array that combines the passed two arrays, maintaining the order.
   *
   * @param 
   *        Array element type
   * @param aHeadArray
   *        The first array. May be null.
   * @param aTailArray
   *        The second array. May be null.
   * @return null if both array parameters are null -
   *         a non-null array with all elements in the correct
   *         order otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static  ELEMENTTYPE [] getConcatenated (@Nullable final ELEMENTTYPE [] aHeadArray,
                                                              @Nullable final ELEMENTTYPE [] aTailArray)
  {
    // If first array is invalid, simply
    if (isEmpty (aHeadArray))
      return getCopy (aTailArray);
    if (isEmpty (aTailArray))
      return getCopy (aHeadArray);

    // Start concatenating
    final ELEMENTTYPE [] ret = newArraySameType (aHeadArray, aHeadArray.length + aTailArray.length);
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    System.arraycopy (aTailArray, 0, ret, aHeadArray.length, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed head and the array. The head
   * element will be the first element of the created array.
   *
   * @param 
   *        Array element type
   * @param aHead
   *        The first element of the result array. If this element is
   *        null it will be inserted as such into the array!
   * @param aTailArray
   *        The tail array. May be null.
   * @param aClass
   *        The element class. Must be present, because in case both elements
   *        are null there would be no way to create a new array.
   *        May not be null.
   * @return null if both array parameters are null -
   *         a non-null array with all elements in the correct
   *         order otherwise.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static  ELEMENTTYPE [] getConcatenated (@Nullable final ELEMENTTYPE aHead,
                                                              @Nullable final ELEMENTTYPE [] aTailArray,
                                                              @Nonnull final Class  aClass)
  {
    if (isEmpty (aTailArray))
      return newArraySingleElement (aHead, aClass);

    // Start concatenating
    final ELEMENTTYPE [] ret = newArray (aClass, 1 + aTailArray.length);
    ret[0] = aHead;
    System.arraycopy (aTailArray, 0, ret, 1, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed array and the tail element. The
   * tail element will be the last element of the created array.
   *
   * @param 
   *        Array element type
   * @param aHeadArray
   *        The head array. May be null.
   * @param aTail
   *        The last element of the result array. If this element is
   *        null it will be inserted as such into the array!
   * @param aClass
   *        The element class. Must be present, because in case both elements
   *        are null there would be no way to create a new array.
   *        May not be null.
   * @return null if both array parameters are null -
   *         a non-null array with all elements in the correct
   *         order otherwise.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static  ELEMENTTYPE [] getConcatenated (@Nullable final ELEMENTTYPE [] aHeadArray,
                                                              @Nullable final ELEMENTTYPE aTail,
                                                              @Nonnull final Class  aClass)
  {
    if (isEmpty (aHeadArray))
      return newArraySingleElement (aTail, aClass);

    // Start concatenating
    final ELEMENTTYPE [] ret = newArray (aClass, aHeadArray.length + 1);
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    ret[aHeadArray.length] = aTail;
    return ret;
  }

  /**
   * Get a new array that combines the passed two arrays, maintaining the order.
   *
   * @param aHeadArray
   *        The first array. May be null.
   * @param aTailArray
   *        The second array. May be null.
   * @return null if both array parameters are null -
   *         a non-null array with all elements in the correct
   *         order otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static boolean [] getConcatenated (@Nullable final boolean [] aHeadArray, @Nullable final boolean... aTailArray)
  {
    // If first array is invalid, simply
    if (isEmpty (aHeadArray))
      return getCopy (aTailArray);
    if (isEmpty (aTailArray))
      return getCopy (aHeadArray);

    // Start concatenating
    final boolean [] ret = new boolean [aHeadArray.length + aTailArray.length];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    System.arraycopy (aTailArray, 0, ret, aHeadArray.length, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed head element and the array. The
   * head element will be the first element of the created array.
   *
   * @param aHead
   *        The first element of the result array.
   * @param aTailArray
   *        The tail array. May be null.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static boolean [] getConcatenated (final boolean aHead, @Nullable final boolean... aTailArray)
  {
    if (isEmpty (aTailArray))
      return new boolean [] { aHead };

    final boolean [] ret = new boolean [1 + aTailArray.length];
    ret[0] = aHead;
    System.arraycopy (aTailArray, 0, ret, 1, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed array and the tail element. The
   * tail element will be the last element of the created array.
   *
   * @param aHeadArray
   *        The head array. May be null.
   * @param aTail
   *        The last element of the result array.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static boolean [] getConcatenated (@Nullable final boolean [] aHeadArray, final boolean aTail)
  {
    if (isEmpty (aHeadArray))
      return new boolean [] { aTail };

    final boolean [] ret = new boolean [aHeadArray.length + 1];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    ret[aHeadArray.length] = aTail;
    return ret;
  }

  /**
   * Get a new array that combines the passed two arrays, maintaining the order.
   *
   * @param aHeadArray
   *        The first array. May be null.
   * @param aTailArray
   *        The second array. May be null.
   * @return null if both array parameters are null -
   *         a non-null array with all elements in the correct
   *         order otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static byte [] getConcatenated (@Nullable final byte [] aHeadArray, @Nullable final byte... aTailArray)
  {
    // If first array is invalid, simply
    if (isEmpty (aHeadArray))
      return getCopy (aTailArray);
    if (isEmpty (aTailArray))
      return getCopy (aHeadArray);

    // Start concatenating
    final byte [] ret = new byte [aHeadArray.length + aTailArray.length];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    System.arraycopy (aTailArray, 0, ret, aHeadArray.length, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed head element and the array. The
   * head element will be the first element of the created array.
   *
   * @param aHead
   *        The first element of the result array.
   * @param aTailArray
   *        The tail array. May be null.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static byte [] getConcatenated (final byte aHead, @Nullable final byte... aTailArray)
  {
    if (isEmpty (aTailArray))
      return new byte [] { aHead };

    final byte [] ret = new byte [1 + aTailArray.length];
    ret[0] = aHead;
    System.arraycopy (aTailArray, 0, ret, 1, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed array and the tail element. The
   * tail element will be the last element of the created array.
   *
   * @param aHeadArray
   *        The head array. May be null.
   * @param aTail
   *        The last element of the result array.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static byte [] getConcatenated (@Nullable final byte [] aHeadArray, final byte aTail)
  {
    if (isEmpty (aHeadArray))
      return new byte [] { aTail };

    final byte [] ret = new byte [aHeadArray.length + 1];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    ret[aHeadArray.length] = aTail;
    return ret;
  }

  /**
   * Get a new array that combines the passed two arrays, maintaining the order.
   *
   * @param aHeadArray
   *        The first array. May be null.
   * @param aTailArray
   *        The second array. May be null.
   * @return null if both array parameters are null -
   *         a non-null array with all elements in the correct
   *         order otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static char [] getConcatenated (@Nullable final char [] aHeadArray, @Nullable final char... aTailArray)
  {
    // If first array is invalid, simply
    if (isEmpty (aHeadArray))
      return getCopy (aTailArray);
    if (isEmpty (aTailArray))
      return getCopy (aHeadArray);

    // Start concatenating
    final char [] ret = new char [aHeadArray.length + aTailArray.length];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    System.arraycopy (aTailArray, 0, ret, aHeadArray.length, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed two arrays, maintaining the order.
   *
   * @param aHeadArray
   *        The first array. May be null.
   * @param aTailArray
   *        The second array. May be null.
   * @return null if both array parameters are null -
   *         a non-null array with all elements in the correct
   *         order otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static char [] [] getConcatenated (@Nullable final char [] [] aHeadArray, @Nullable final char []... aTailArray)
  {
    // If first array is invalid, simply
    if (isEmpty (aHeadArray))
      return getCopy (aTailArray);
    if (isEmpty (aTailArray))
      return getCopy (aHeadArray);

    // Start concatenating
    final char [] [] ret = new char [aHeadArray.length + aTailArray.length] [];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    System.arraycopy (aTailArray, 0, ret, aHeadArray.length, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed head element and the array. The
   * head element will be the first element of the created array.
   *
   * @param aHead
   *        The first element of the result array.
   * @param aTailArray
   *        The tail array. May be null.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static char [] getConcatenated (final char aHead, @Nullable final char... aTailArray)
  {
    if (isEmpty (aTailArray))
      return new char [] { aHead };

    final char [] ret = new char [1 + aTailArray.length];
    ret[0] = aHead;
    System.arraycopy (aTailArray, 0, ret, 1, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed array and the tail element. The
   * tail element will be the last element of the created array.
   *
   * @param aHeadArray
   *        The head array. May be null.
   * @param aTail
   *        The last element of the result array.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static char [] getConcatenated (@Nullable final char [] aHeadArray, final char aTail)
  {
    if (isEmpty (aHeadArray))
      return new char [] { aTail };

    final char [] ret = new char [aHeadArray.length + 1];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    ret[aHeadArray.length] = aTail;
    return ret;
  }

  /**
   * Get a new array that combines the passed two arrays, maintaining the order.
   *
   * @param aHeadArray
   *        The first array. May be null.
   * @param aTailArray
   *        The second array. May be null.
   * @return null if both array parameters are null -
   *         a non-null array with all elements in the correct
   *         order otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static double [] getConcatenated (@Nullable final double [] aHeadArray, @Nullable final double... aTailArray)
  {
    // If first array is invalid, simply
    if (isEmpty (aHeadArray))
      return getCopy (aTailArray);
    if (isEmpty (aTailArray))
      return getCopy (aHeadArray);

    // Start concatenating
    final double [] ret = new double [aHeadArray.length + aTailArray.length];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    System.arraycopy (aTailArray, 0, ret, aHeadArray.length, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed head element and the array. The
   * head element will be the first element of the created array.
   *
   * @param aHead
   *        The first element of the result array.
   * @param aTailArray
   *        The tail array. May be null.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static double [] getConcatenated (final double aHead, @Nullable final double... aTailArray)
  {
    if (isEmpty (aTailArray))
      return new double [] { aHead };

    final double [] ret = new double [1 + aTailArray.length];
    ret[0] = aHead;
    System.arraycopy (aTailArray, 0, ret, 1, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed array and the tail element. The
   * tail element will be the last element of the created array.
   *
   * @param aHeadArray
   *        The head array. May be null.
   * @param aTail
   *        The last element of the result array.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static double [] getConcatenated (@Nullable final double [] aHeadArray, final double aTail)
  {
    if (isEmpty (aHeadArray))
      return new double [] { aTail };

    final double [] ret = new double [aHeadArray.length + 1];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    ret[aHeadArray.length] = aTail;
    return ret;
  }

  /**
   * Get a new array that combines the passed two arrays, maintaining the order.
   *
   * @param aHeadArray
   *        The first array. May be null.
   * @param aTailArray
   *        The second array. May be null.
   * @return null if both array parameters are null -
   *         a non-null array with all elements in the correct
   *         order otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static float [] getConcatenated (@Nullable final float [] aHeadArray, @Nullable final float... aTailArray)
  {
    // If first array is invalid, simply
    if (isEmpty (aHeadArray))
      return getCopy (aTailArray);
    if (isEmpty (aTailArray))
      return getCopy (aHeadArray);

    // Start concatenating
    final float [] ret = new float [aHeadArray.length + aTailArray.length];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    System.arraycopy (aTailArray, 0, ret, aHeadArray.length, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed head element and the array. The
   * head element will be the first element of the created array.
   *
   * @param aHead
   *        The first element of the result array.
   * @param aTailArray
   *        The tail array. May be null.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static float [] getConcatenated (final float aHead, @Nullable final float... aTailArray)
  {
    if (isEmpty (aTailArray))
      return new float [] { aHead };

    final float [] ret = new float [1 + aTailArray.length];
    ret[0] = aHead;
    System.arraycopy (aTailArray, 0, ret, 1, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed array and the tail element. The
   * tail element will be the last element of the created array.
   *
   * @param aHeadArray
   *        The head array. May be null.
   * @param aTail
   *        The last element of the result array.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static float [] getConcatenated (@Nullable final float [] aHeadArray, final float aTail)
  {
    if (isEmpty (aHeadArray))
      return new float [] { aTail };

    final float [] ret = new float [aHeadArray.length + 1];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    ret[aHeadArray.length] = aTail;
    return ret;
  }

  /**
   * Get a new array that combines the passed two arrays, maintaining the order.
   *
   * @param aHeadArray
   *        The first array. May be null.
   * @param aTailArray
   *        The second array. May be null.
   * @return null if both array parameters are null -
   *         a non-null array with all elements in the correct
   *         order otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static int [] getConcatenated (@Nullable final int [] aHeadArray, @Nullable final int... aTailArray)
  {
    // If first array is invalid, simply
    if (isEmpty (aHeadArray))
      return getCopy (aTailArray);
    if (isEmpty (aTailArray))
      return getCopy (aHeadArray);

    // Start concatenating
    final int [] ret = new int [aHeadArray.length + aTailArray.length];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    System.arraycopy (aTailArray, 0, ret, aHeadArray.length, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed head element and the array. The
   * head element will be the first element of the created array.
   *
   * @param aHead
   *        The first element of the result array.
   * @param aTailArray
   *        The tail array. May be null.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static int [] getConcatenated (final int aHead, @Nullable final int... aTailArray)
  {
    if (isEmpty (aTailArray))
      return new int [] { aHead };

    final int [] ret = new int [1 + aTailArray.length];
    ret[0] = aHead;
    System.arraycopy (aTailArray, 0, ret, 1, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed array and the tail element. The
   * tail element will be the last element of the created array.
   *
   * @param aHeadArray
   *        The head array. May be null.
   * @param aTail
   *        The last element of the result array.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static int [] getConcatenated (@Nullable final int [] aHeadArray, final int aTail)
  {
    if (isEmpty (aHeadArray))
      return new int [] { aTail };

    final int [] ret = new int [aHeadArray.length + 1];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    ret[aHeadArray.length] = aTail;
    return ret;
  }

  /**
   * Get a new array that combines the passed two arrays, maintaining the order.
   *
   * @param aHeadArray
   *        The first array. May be null.
   * @param aTailArray
   *        The second array. May be null.
   * @return null if both array parameters are null -
   *         a non-null array with all elements in the correct
   *         order otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static long [] getConcatenated (@Nullable final long [] aHeadArray, @Nullable final long... aTailArray)
  {
    // If first array is invalid, simply
    if (isEmpty (aHeadArray))
      return getCopy (aTailArray);
    if (isEmpty (aTailArray))
      return getCopy (aHeadArray);

    // Start concatenating
    final long [] ret = new long [aHeadArray.length + aTailArray.length];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    System.arraycopy (aTailArray, 0, ret, aHeadArray.length, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed head element and the array. The
   * head element will be the first element of the created array.
   *
   * @param aHead
   *        The first element of the result array.
   * @param aTailArray
   *        The tail array. May be null.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static long [] getConcatenated (final long aHead, @Nullable final long... aTailArray)
  {
    if (isEmpty (aTailArray))
      return new long [] { aHead };

    final long [] ret = new long [1 + aTailArray.length];
    ret[0] = aHead;
    System.arraycopy (aTailArray, 0, ret, 1, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed array and the tail element. The
   * tail element will be the last element of the created array.
   *
   * @param aHeadArray
   *        The head array. May be null.
   * @param aTail
   *        The last element of the result array.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static long [] getConcatenated (@Nullable final long [] aHeadArray, final long aTail)
  {
    if (isEmpty (aHeadArray))
      return new long [] { aTail };

    final long [] ret = new long [aHeadArray.length + 1];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    ret[aHeadArray.length] = aTail;
    return ret;
  }

  /**
   * Get a new array that combines the passed two arrays, maintaining the order.
   *
   * @param aHeadArray
   *        The first array. May be null.
   * @param aTailArray
   *        The second array. May be null.
   * @return null if both array parameters are null -
   *         a non-null array with all elements in the correct
   *         order otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static short [] getConcatenated (@Nullable final short [] aHeadArray, @Nullable final short... aTailArray)
  {
    // If first array is invalid, simply
    if (isEmpty (aHeadArray))
      return getCopy (aTailArray);
    if (isEmpty (aTailArray))
      return getCopy (aHeadArray);

    // Start concatenating
    final short [] ret = new short [aHeadArray.length + aTailArray.length];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    System.arraycopy (aTailArray, 0, ret, aHeadArray.length, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed head element and the array. The
   * head element will be the first element of the created array.
   *
   * @param aHead
   *        The first element of the result array.
   * @param aTailArray
   *        The tail array. May be null.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static short [] getConcatenated (final short aHead, @Nullable final short... aTailArray)
  {
    if (isEmpty (aTailArray))
      return new short [] { aHead };

    final short [] ret = new short [1 + aTailArray.length];
    ret[0] = aHead;
    System.arraycopy (aTailArray, 0, ret, 1, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed array and the tail element. The
   * tail element will be the last element of the created array.
   *
   * @param aHeadArray
   *        The head array. May be null.
   * @param aTail
   *        The last element of the result array.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static short [] getConcatenated (@Nullable final short [] aHeadArray, final short aTail)
  {
    if (isEmpty (aHeadArray))
      return new short [] { aTail };

    final short [] ret = new short [aHeadArray.length + 1];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    ret[aHeadArray.length] = aTail;
    return ret;
  }

  /**
   * Get a new array that combines the passed two arrays, maintaining the order.
   *
   * @param aHeadArray
   *        The first array. May be null.
   * @param aTailArray
   *        The second array. May be null.
   * @return null if both array parameters are null -
   *         a non-null array with all elements in the correct
   *         order otherwise.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static String [] getConcatenated (@Nullable final String [] aHeadArray, @Nullable final String... aTailArray)
  {
    // If first array is invalid, simply
    if (isEmpty (aHeadArray))
      return getCopy (aTailArray);
    if (isEmpty (aTailArray))
      return getCopy (aHeadArray);

    // Start concatenating
    final String [] ret = new String [aHeadArray.length + aTailArray.length];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    System.arraycopy (aTailArray, 0, ret, aHeadArray.length, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed head element and the array. The
   * head element will be the first element of the created array.
   *
   * @param aHead
   *        The first element of the result array.
   * @param aTailArray
   *        The tail array. May be null.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static String [] getConcatenated (final String aHead, @Nullable final String... aTailArray)
  {
    if (isEmpty (aTailArray))
      return new String [] { aHead };

    final String [] ret = new String [1 + aTailArray.length];
    ret[0] = aHead;
    System.arraycopy (aTailArray, 0, ret, 1, aTailArray.length);
    return ret;
  }

  /**
   * Get a new array that combines the passed array and the tail element. The
   * tail element will be the last element of the created array.
   *
   * @param aHeadArray
   *        The head array. May be null.
   * @param aTail
   *        The last element of the result array.
   * @return A non-null array with all elements in the correct
   *         order.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static String [] getConcatenated (@Nullable final String [] aHeadArray, final String aTail)
  {
    if (isEmpty (aHeadArray))
      return new String [] { aTail };

    final String [] ret = new String [aHeadArray.length + 1];
    System.arraycopy (aHeadArray, 0, ret, 0, aHeadArray.length);
    ret[aHeadArray.length] = aTail;
    return ret;
  }

  /**
   * Get an array that contains all elements, except for the first element.
   *
   * @param 
   *        Array element type
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the first element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  @SafeVarargs
  public static  ELEMENTTYPE [] getAllExceptFirst (@Nullable final ELEMENTTYPE... aArray)
  {
    return getAllExceptFirst (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the first n
   * elements.
   *
   * @param 
   *        Array element type
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the first elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static  ELEMENTTYPE [] getAllExceptFirst (@Nullable final ELEMENTTYPE [] aArray,
                                                                @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, nElementsToSkip, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the passed elements.
   *
   * @param 
   *        Array element type
   * @param aArray
   *        The source array. May be null.
   * @param aElementsToRemove
   *        The elements to skip.
   * @return null if the passed array is null. The
   *         original array, if no elements need to be skipped. A non-
   *         null copy of the array without the passed elements
   *         otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  @SafeVarargs
  public static  ELEMENTTYPE [] getAllExcept (@Nullable final ELEMENTTYPE [] aArray,
                                                           @Nullable final ELEMENTTYPE... aElementsToRemove)
  {
    if (isEmpty (aArray) || isEmpty (aElementsToRemove))
      return aArray;

    final ELEMENTTYPE [] tmp = getCopy (aArray);
    int nDst = 0;
    for (int nSrc = 0; nSrc < tmp.length; ++nSrc)
      if (!contains (aElementsToRemove, tmp[nSrc]))
        tmp[nDst++] = tmp[nSrc];
    return getCopy (tmp, 0, nDst);
  }

  /**
   * Get an array that contains all elements, except for the passed elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param aElementsToRemove
   *        The elements to skip.
   * @return null if the passed array is null. The
   *         original array, if no elements need to be skipped. A non-
   *         null copy of the array without the passed elements
   *         otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static boolean [] getAllExcept (@Nullable final boolean [] aArray, @Nullable final boolean... aElementsToRemove)
  {
    if (isEmpty (aArray) || isEmpty (aElementsToRemove))
      return aArray;

    final boolean [] tmp = getCopy (aArray);
    int nDst = 0;
    for (int nSrc = 0; nSrc < tmp.length; ++nSrc)
      if (!contains (aElementsToRemove, tmp[nSrc]))
        tmp[nDst++] = tmp[nSrc];
    return getCopy (tmp, 0, nDst);
  }

  /**
   * Get an array that contains all elements, except for the passed elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param aElementsToRemove
   *        The elements to skip.
   * @return null if the passed array is null. The
   *         original array, if no elements need to be skipped. A non-
   *         null copy of the array without the passed elements
   *         otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static byte [] getAllExcept (@Nullable final byte [] aArray, @Nullable final byte... aElementsToRemove)
  {
    if (isEmpty (aArray) || isEmpty (aElementsToRemove))
      return aArray;

    final byte [] tmp = getCopy (aArray);
    int nDst = 0;
    for (int nSrc = 0; nSrc < tmp.length; ++nSrc)
      if (!contains (aElementsToRemove, tmp[nSrc]))
        tmp[nDst++] = tmp[nSrc];
    return getCopy (tmp, 0, nDst);
  }

  /**
   * Get an array that contains all elements, except for the passed elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param aElementsToRemove
   *        The elements to skip.
   * @return null if the passed array is null. The
   *         original array, if no elements need to be skipped. A non-
   *         null copy of the array without the passed elements
   *         otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static char [] getAllExcept (@Nullable final char [] aArray, @Nullable final char... aElementsToRemove)
  {
    if (isEmpty (aArray) || isEmpty (aElementsToRemove))
      return aArray;

    final char [] tmp = getCopy (aArray);
    int nDst = 0;
    for (int nSrc = 0; nSrc < tmp.length; ++nSrc)
      if (!contains (aElementsToRemove, tmp[nSrc]))
        tmp[nDst++] = tmp[nSrc];
    return getCopy (tmp, 0, nDst);
  }

  /**
   * Get an array that contains all elements, except for the passed elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param aElementsToRemove
   *        The elements to skip.
   * @return null if the passed array is null. The
   *         original array, if no elements need to be skipped. A non-
   *         null copy of the array without the passed elements
   *         otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static double [] getAllExcept (@Nullable final double [] aArray, @Nullable final double... aElementsToRemove)
  {
    if (isEmpty (aArray) || isEmpty (aElementsToRemove))
      return aArray;

    final double [] tmp = getCopy (aArray);
    int nDst = 0;
    for (int nSrc = 0; nSrc < tmp.length; ++nSrc)
      if (!contains (aElementsToRemove, tmp[nSrc]))
        tmp[nDst++] = tmp[nSrc];
    return getCopy (tmp, 0, nDst);
  }

  /**
   * Get an array that contains all elements, except for the passed elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param aElementsToRemove
   *        The elements to skip.
   * @return null if the passed array is null. The
   *         original array, if no elements need to be skipped. A non-
   *         null copy of the array without the passed elements
   *         otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static float [] getAllExcept (@Nullable final float [] aArray, @Nullable final float... aElementsToRemove)
  {
    if (isEmpty (aArray) || isEmpty (aElementsToRemove))
      return aArray;

    final float [] tmp = getCopy (aArray);
    int nDst = 0;
    for (int nSrc = 0; nSrc < tmp.length; ++nSrc)
      if (!contains (aElementsToRemove, tmp[nSrc]))
        tmp[nDst++] = tmp[nSrc];
    return getCopy (tmp, 0, nDst);
  }

  /**
   * Get an array that contains all elements, except for the passed elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param aElementsToRemove
   *        The elements to skip.
   * @return null if the passed array is null. The
   *         original array, if no elements need to be skipped. A non-
   *         null copy of the array without the passed elements
   *         otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static int [] getAllExcept (@Nullable final int [] aArray, @Nullable final int... aElementsToRemove)
  {
    if (isEmpty (aArray) || isEmpty (aElementsToRemove))
      return aArray;

    final int [] tmp = getCopy (aArray);
    int nDst = 0;
    for (int nSrc = 0; nSrc < tmp.length; ++nSrc)
      if (!contains (aElementsToRemove, tmp[nSrc]))
        tmp[nDst++] = tmp[nSrc];
    return getCopy (tmp, 0, nDst);
  }

  /**
   * Get an array that contains all elements, except for the passed elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param aElementsToRemove
   *        The elements to skip.
   * @return null if the passed array is null. The
   *         original array, if no elements need to be skipped. A non-
   *         null copy of the array without the passed elements
   *         otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static long [] getAllExcept (@Nullable final long [] aArray, @Nullable final long... aElementsToRemove)
  {
    if (isEmpty (aArray) || isEmpty (aElementsToRemove))
      return aArray;

    final long [] tmp = getCopy (aArray);
    int nDst = 0;
    for (int nSrc = 0; nSrc < tmp.length; ++nSrc)
      if (!contains (aElementsToRemove, tmp[nSrc]))
        tmp[nDst++] = tmp[nSrc];
    return getCopy (tmp, 0, nDst);
  }

  /**
   * Get an array that contains all elements, except for the passed elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param aElementsToRemove
   *        The elements to skip.
   * @return null if the passed array is null. The
   *         original array, if no elements need to be skipped. A non-
   *         null copy of the array without the passed elements
   *         otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static short [] getAllExcept (@Nullable final short [] aArray, @Nullable final short... aElementsToRemove)
  {
    if (isEmpty (aArray) || isEmpty (aElementsToRemove))
      return aArray;

    final short [] tmp = getCopy (aArray);
    int nDst = 0;
    for (int nSrc = 0; nSrc < tmp.length; ++nSrc)
      if (!contains (aElementsToRemove, tmp[nSrc]))
        tmp[nDst++] = tmp[nSrc];
    return getCopy (tmp, 0, nDst);
  }

  /**
   * Get an array that contains all elements, except for the first element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the first element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static boolean [] getAllExceptFirst (@Nullable final boolean... aArray)
  {
    return getAllExceptFirst (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the first n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the first elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static boolean [] getAllExceptFirst (@Nullable final boolean [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, nElementsToSkip, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the first element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the first element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static byte [] getAllExceptFirst (@Nullable final byte... aArray)
  {
    return getAllExceptFirst (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the first n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the first elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static byte [] getAllExceptFirst (@Nullable final byte [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, nElementsToSkip, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the first element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the first element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static char [] getAllExceptFirst (@Nullable final char... aArray)
  {
    return getAllExceptFirst (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the first n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the first elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static char [] getAllExceptFirst (@Nullable final char [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, nElementsToSkip, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the first element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the first element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static double [] getAllExceptFirst (@Nullable final double... aArray)
  {
    return getAllExceptFirst (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the first n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the first elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static double [] getAllExceptFirst (@Nullable final double [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, nElementsToSkip, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the first element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the first element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static float [] getAllExceptFirst (@Nullable final float... aArray)
  {
    return getAllExceptFirst (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the first n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the first elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static float [] getAllExceptFirst (@Nullable final float [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, nElementsToSkip, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the first element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the first element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static int [] getAllExceptFirst (@Nullable final int... aArray)
  {
    return getAllExceptFirst (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the first n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the first elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static int [] getAllExceptFirst (@Nullable final int [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, nElementsToSkip, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the first element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the first element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static long [] getAllExceptFirst (@Nullable final long... aArray)
  {
    return getAllExceptFirst (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the first n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the first elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static long [] getAllExceptFirst (@Nullable final long [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, nElementsToSkip, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the first element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the first element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static short [] getAllExceptFirst (@Nullable final short... aArray)
  {
    return getAllExceptFirst (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the first n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the first elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static short [] getAllExceptFirst (@Nullable final short [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, nElementsToSkip, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the last element.
   *
   * @param 
   *        Array element type
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the last element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  @SafeVarargs
  public static  ELEMENTTYPE [] getAllExceptLast (@Nullable final ELEMENTTYPE... aArray)
  {
    return getAllExceptLast (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the last n
   * elements.
   *
   * @param 
   *        Type of element
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the last elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static  ELEMENTTYPE [] getAllExceptLast (@Nullable final ELEMENTTYPE [] aArray,
                                                               @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, 0, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the last element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the last element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static boolean [] getAllExceptLast (@Nullable final boolean... aArray)
  {
    return getAllExceptLast (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the last n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the last elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static boolean [] getAllExceptLast (@Nullable final boolean [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, 0, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the last element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the last element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static byte [] getAllExceptLast (@Nullable final byte... aArray)
  {
    return getAllExceptLast (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the last n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the last elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static byte [] getAllExceptLast (@Nullable final byte [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, 0, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the last element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the last element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static char [] getAllExceptLast (@Nullable final char... aArray)
  {
    return getAllExceptLast (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the last n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the last elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static char [] getAllExceptLast (@Nullable final char [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, 0, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the last element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the last element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static double [] getAllExceptLast (@Nullable final double... aArray)
  {
    return getAllExceptLast (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the last n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the last elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static double [] getAllExceptLast (@Nullable final double [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, 0, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the last element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the last element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static float [] getAllExceptLast (@Nullable final float... aArray)
  {
    return getAllExceptLast (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the last n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the last elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static float [] getAllExceptLast (@Nullable final float [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, 0, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the last element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the last element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static int [] getAllExceptLast (@Nullable final int... aArray)
  {
    return getAllExceptLast (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the last n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the last elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static int [] getAllExceptLast (@Nullable final int [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, 0, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the last element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the last element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static long [] getAllExceptLast (@Nullable final long... aArray)
  {
    return getAllExceptLast (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the last n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the last elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static long [] getAllExceptLast (@Nullable final long [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, 0, aArray.length - nElementsToSkip);
  }

  /**
   * Get an array that contains all elements, except for the last element.
   *
   * @param aArray
   *        The source array. May be null.
   * @return null if the passed array is null or has
   *         less than one element. A non-null copy of the array
   *         without the last element otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static short [] getAllExceptLast (@Nullable final short... aArray)
  {
    return getAllExceptLast (aArray, 1);
  }

  /**
   * Get an array that contains all elements, except for the last n
   * elements.
   *
   * @param aArray
   *        The source array. May be null.
   * @param nElementsToSkip
   *        The number of elements to skip. Must be >= 0!
   * @return null if the passed array is null or has
   *         ≤ elements than elements to be skipped. A non-null
   *         copy of the array without the last elements otherwise.
   */
  @Nullable
  @ReturnsMutableCopy
  public static short [] getAllExceptLast (@Nullable final short [] aArray, @Nonnegative final int nElementsToSkip)
  {
    ValueEnforcer.isGE0 (nElementsToSkip, "ElementsToSkip");

    if (nElementsToSkip == 0)
      return aArray;
    if (aArray == null || nElementsToSkip >= aArray.length)
      return null;
    return getCopy (aArray, 0, aArray.length - nElementsToSkip);
  }

  /**
   * Helper method to easily create an array from constant values.
   *
   * @param aArray
   *        The list of values for the array. May be null.
   * @return The passed array. null if the passed array was
   *         null.
   */
  @Nullable
  @ReturnsMutableObject ("use getCopy otherwise")
  public static boolean [] newBooleanArray (@Nullable final boolean... aArray)
  {
    return aArray;
  }

  /**
   * Helper method to easily create an array from constant values.
   *
   * @param aArray
   *        The list of values for the array. May be null.
   * @return The passed array. null if the passed array was
   *         null.
   */
  @Nullable
  @ReturnsMutableObject ("use getCopy otherwise")
  public static byte [] newByteArray (@Nullable final byte... aArray)
  {
    return aArray;
  }

  /**
   * Helper method to easily create an array from constant values.
   *
   * @param aArray
   *        The list of values for the array. May be null.
   * @return The passed array. null if the passed array was
   *         null.
   */
  @Nullable
  @ReturnsMutableObject ("use getCopy otherwise")
  public static char [] newCharArray (@Nullable final char... aArray)
  {
    return aArray;
  }

  /**
   * Helper method to easily create an array from constant values.
   *
   * @param aArray
   *        The list of values for the array. May be null.
   * @return The passed array. null if the passed array was
   *         null.
   */
  @Nullable
  @ReturnsMutableObject ("use getCopy otherwise")
  public static double [] newDoubleArray (@Nullable final double... aArray)
  {
    return aArray;
  }

  /**
   * Helper method to easily create an array from constant values.
   *
   * @param aArray
   *        The list of values for the array. May be null.
   * @return The passed array. null if the passed array was
   *         null.
   */
  @Nullable
  @ReturnsMutableObject ("use getCopy otherwise")
  public static float [] newFloatArray (@Nullable final float... aArray)
  {
    return aArray;
  }

  /**
   * Helper method to easily create an array from constant values.
   *
   * @param aArray
   *        The list of values for the array. May be null.
   * @return The passed array. null if the passed array was
   *         null.
   */
  @Nullable
  @ReturnsMutableObject ("use getCopy otherwise")
  public static int [] newIntArray (@Nullable final int... aArray)
  {
    return aArray;
  }

  /**
   * Helper method to easily create an array from constant values.
   *
   * @param aArray
   *        The list of values for the array. May be null.
   * @return The passed array. null if the passed array was
   *         null.
   */
  @Nullable
  @ReturnsMutableObject ("use getCopy otherwise")
  public static long [] newLongArray (@Nullable final long... aArray)
  {
    return aArray;
  }

  /**
   * Helper method to easily create an array from constant values.
   *
   * @param aArray
   *        The list of values for the array. May be null.
   * @return The passed array. null if the passed array was
   *         null.
   */
  @Nullable
  @ReturnsMutableObject ("use getCopy otherwise")
  public static short [] newShortArray (@Nullable final short... aArray)
  {
    return aArray;
  }

  @Nonnull
  @ReturnsMutableCopy
  public static  ELEMENTTYPE [] newArray (@Nonnull final Class  aClass, @Nonnegative final int nSize)
  {
    ValueEnforcer.notNull (aClass, "class");
    if (aClass.isPrimitive ())
      throw new IllegalArgumentException ("Argument cannot be primitive: " + aClass);
    ValueEnforcer.isGE0 (nSize, "Size");

    final Object aArray = Array.newInstance (aClass, nSize);
    return GenericReflection.uncheckedCast (aArray);
  }

  /**
   * Create a new empty array with the same type as the passed array.
   *
   * @param 
   *        Type of element
   * @param aArray
   *        Source array. May not be null.
   * @param nSize
   *        Destination size. Must be ≥ 0.
   * @return Never null.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static  ELEMENTTYPE [] newArraySameType (@Nonnull final ELEMENTTYPE [] aArray, @Nonnegative final int nSize)
  {
    return newArray (getComponentType (aArray), nSize);
  }

  /**
   * Create a new array with the elements in the passed collection..
   *
   * @param 
   *        Type of element
   * @param aCollection
   *        The collection to be converted to an array. May be null
   *        .
   * @param aClass
   *        The class of the elements inside the collection. May not be
   *        null.
   * @return null if the passed collection is empty, a non-
   *         null array with all elements of the collection
   *         otherwise.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static  ELEMENTTYPE [] newArray (@Nullable final Collection  aCollection,
                                                       @Nonnull final Class  aClass)
  {
    ValueEnforcer.notNull (aClass, "class");

    if (CollectionHelper.isEmpty (aCollection))
      return newArray (aClass, 0);

    final ELEMENTTYPE [] ret = newArray (aClass, aCollection.size ());
    return aCollection.toArray (ret);
  }

  /**
   * Wrapper that allows a single argument to be treated as an array.
   *
   * @param 
   *        Type of element
   * @param aElement
   *        The element to be converted to an array. May be null.
   * @param aClass
   *        The class of the element. May not be null. Must be
   *        present because in case the passed element is null
   *        there is no way to determine the array component type!
   * @return The created array and never null.
   */
  @Nonnull
  @ReturnsMutableCopy
  public static  ELEMENTTYPE [] newArraySingleElement (@Nullable final ELEMENTTYPE aElement,
                                                                    @Nonnull final Class  aClass)
  {
    ValueEnforcer.notNull (aClass, "class");

    final ELEMENTTYPE [] ret = newArray (aClass, 1);
    ret[0] = aElement;
    return ret;
  }

  /**
   * Wrapper that allows vararg arguments and returns the array. 
* Note: this implementation is not available for basic types, because the * Eclipse compiler seems to have difficulties resolving vararg types * correctly. * * @param * Type of element * @param aArray * The vararg array * @return The wrapped array */ @Nonnull @ReturnsMutableObject ("use getCopy otherwise") @SafeVarargs public static ELEMENTTYPE [] newArray (@Nonnull final ELEMENTTYPE... aArray) { ValueEnforcer.notNull (aArray, "Array"); return aArray; } /** * Create a new array with a predefined number of elements containing the * passed value. * * @param * The type of the array to be created. * @param nArraySize * The size of the array to be created. * @param aValue * The value to be set into each array element. May be * null. * @param aClass * The value class. May not be null. Must be present in * case the passed value is null. * @return The created array filled with the given value. */ @Nonnull @ReturnsMutableCopy public static ELEMENTTYPE [] newArray (@Nonnegative final int nArraySize, @Nonnull final ELEMENTTYPE aValue, @Nonnull final Class aClass) { ValueEnforcer.isGE0 (nArraySize, "ArraySize"); ValueEnforcer.notNull (aClass, "class"); final ELEMENTTYPE [] ret = newArray (aClass, nArraySize); Arrays.fill (ret, aValue); return ret; } @Nonnull @ReturnsMutableCopy public static DSTTYPE [] newArrayMapped (@Nonnull final Collection aCollection, @Nonnull final Function aMapper, @Nonnull final Class aDstClass) { ValueEnforcer.notNull (aCollection, "Collection"); ValueEnforcer.notNull (aMapper, "Converter"); ValueEnforcer.notNull (aDstClass, "DestClass"); final DSTTYPE [] ret = ArrayHelper.newArray (aDstClass, aCollection.size ()); int i = 0; for (final SRCTYPE aObj : aCollection) ret[i++] = aMapper.apply (aObj); return ret; } @Nonnull @ReturnsMutableCopy public static DSTTYPE [] newArrayMapped (@Nullable final SRCTYPE [] aArray, @Nonnull final Function aMapper, @Nonnull final Class aDstClass) { ValueEnforcer.notNull (aMapper, "Converter"); ValueEnforcer.notNull (aDstClass, "DestClass"); final DSTTYPE [] ret = ArrayHelper.newArray (aDstClass, ArrayHelper.getSize (aArray)); if (aArray != null) { int i = 0; for (final SRCTYPE aObj : aArray) ret[i++] = aMapper.apply (aObj); } return ret; } /** * Get the passed collection as an array of Object. If the passed collection * is null or empty, an empty array is returned. * * @param aCollection * The collection to be converted. May be null. * @return Never null. */ @Nullable @ReturnsMutableCopy public static Object [] getAsObjectArray (@Nullable final Collection aCollection) { if (CollectionHelper.isEmpty (aCollection)) return null; final Object [] ret = new Object [aCollection.size ()]; return aCollection.toArray (ret); } @Nullable public static ELEMENTTYPE getSafeElement (@Nullable final ELEMENTTYPE [] aItems, final int nIndex) { return getSafeElement (aItems, nIndex, null); } @Nullable public static ELEMENTTYPE getSafeElement (@Nullable final ELEMENTTYPE [] aItems, final int nIndex, @Nullable final ELEMENTTYPE aDefault) { return aItems != null && nIndex >= 0 && nIndex < aItems.length ? aItems[nIndex] : aDefault; } /** * Recursive equal comparison for arrays. * * @param aHeadArray * First array. May be null. * @param aTailArray * Second array. May be null. * @return true only if the arrays and all contained elements are * recursively equal. */ public static boolean isArrayEquals (@Nullable final Object aHeadArray, @Nullable final Object aTailArray) { // Same objects? if (EqualsHelper.identityEqual (aHeadArray, aTailArray)) return true; // Any of the null -> different because they are not both null if (aHeadArray == null || aTailArray == null) return false; // If any of the passed object is not an array -> not equal as an array, // even if they are equal! if (!isArray (aHeadArray) || !isArray (aTailArray)) return false; // Different component type? if (!aHeadArray.getClass ().getComponentType ().equals (aTailArray.getClass ().getComponentType ())) return false; // Different length? final int nLength = Array.getLength (aHeadArray); if (nLength != Array.getLength (aTailArray)) return false; // Compare step by step for (int i = 0; i < nLength; i++) { final Object aItem1 = Array.get (aHeadArray, i); final Object aItem2 = Array.get (aTailArray, i); if (isArray (aItem1) && isArray (aItem2)) { // Recursive call if (!isArrayEquals (aItem1, aItem2)) return false; } else { // Use equals implementation if (!EqualsHelper.equals (aItem1, aItem2)) return false; } } // No differences found! return true; } /** * Check if the passed array contains at least one null element. * * @param * element type * @param aArray * The array to check. May be null. * @return true only if the passed array is neither * null nor empty and if at least one null * element is contained. */ public static boolean containsAnyNullElement (@Nullable final T [] aArray) { if (aArray != null) for (final T aObj : aArray) if (aObj == null) return true; return false; } /** * Check if the passed array contains only null element. * * @param * element type * @param aArray * The array to check. May be null. * @return true only if the passed array is neither * null nor empty and if at least one null * element is contained. */ public static boolean containsOnlyNullElements (@Nullable final T [] aArray) { if (isEmpty (aArray)) return false; for (final Object aObj : aArray) if (aObj != null) return false; return true; } @Nullable public static ELEMENTTYPE findFirst (@Nullable final ELEMENTTYPE [] aArray, @Nullable final Predicate aFilter) { return findFirst (aArray, aFilter, (ELEMENTTYPE) null); } @Nullable public static ELEMENTTYPE findFirst (@Nullable final ELEMENTTYPE [] aArray, @Nullable final Predicate aFilter, @Nullable final ELEMENTTYPE aDefault) { if (aFilter == null) return getFirst (aArray); if (isNotEmpty (aArray)) for (final ELEMENTTYPE aElement : aArray) if (aFilter.test (aElement)) return aElement; return aDefault; } @Nullable public static RETTYPE findFirstMapped (@Nullable final ELEMENTTYPE [] aArray, @Nullable final Predicate aFilter, @Nonnull final Function aMapper) { return findFirstMapped (aArray, aFilter, aMapper, (RETTYPE) null); } @Nullable public static RETTYPE findFirstMapped (@Nullable final ELEMENTTYPE [] aArray, @Nullable final Predicate aFilter, @Nonnull final Function aMapper, @Nullable final RETTYPE aDefault) { ValueEnforcer.notNull (aMapper, "Mapper"); if (isNotEmpty (aArray)) { if (aFilter == null) return aMapper.apply (aArray[0]); for (final ELEMENTTYPE aElement : aArray) if (aFilter.test (aElement)) return aMapper.apply (aElement); } return aDefault; } @Nonnegative public static int getCount (@Nullable final ELEMENTTYPE [] aArray, @Nullable final Predicate aFilter) { if (aFilter == null) return getSize (aArray); int ret = 0; if (isNotEmpty (aArray)) for (final ELEMENTTYPE aElement : aArray) if (aFilter.test (aElement)) ret++; return ret; } public static boolean containsAny (@Nullable final ELEMENTTYPE [] aArray, @Nullable final Predicate aFilter) { if (aFilter == null) return isNotEmpty (aArray); if (isNotEmpty (aArray)) for (final ELEMENTTYPE aElement : aArray) if (aFilter.test (aElement)) return true; return false; } public static void forEach (@Nullable final ELEMENTTYPE [] aArray, @Nonnull final Consumer aConsumer) { if (isNotEmpty (aArray)) for (final ELEMENTTYPE aElement : aArray) aConsumer.accept (aElement); } public static void forEach (@Nullable final ELEMENTTYPE [] aArray, @Nullable final Predicate aFilter, @Nonnull final Consumer aConsumer) { if (aFilter == null) forEach (aArray, aConsumer); else { if (isNotEmpty (aArray)) for (final ELEMENTTYPE aElement : aArray) if (aFilter.test (aElement)) aConsumer.accept (aElement); } } public static boolean startsWith (@Nonnull final byte [] aArray, @Nullable final byte [] aSearch) { if (aSearch == null) return false; return startsWith (aArray, 0, aArray.length, aSearch, 0, aSearch.length); } public static boolean startsWith (@Nonnull final byte [] aArray, @Nonnegative final int nArrayLen, @Nullable final byte [] aSearch) { if (aSearch == null) return false; return startsWith (aArray, 0, nArrayLen, aSearch, 0, aSearch.length); } public static boolean startsWith (@Nonnull final byte [] aArray, @Nullable final byte [] aSearch, @Nonnegative final int nSearchOfs, @Nonnegative final int nSearchLen) { return startsWith (aArray, 0, aArray.length, aSearch, nSearchOfs, nSearchLen); } public static boolean startsWith (@Nonnull final byte [] aArray, @Nonnegative final int nArrayLen, @Nullable final byte [] aSearch, @Nonnegative final int nSearchOfs, @Nonnegative final int nSearchLen) { return startsWith (aArray, 0, nArrayLen, aSearch, nSearchOfs, nSearchLen); } public static boolean startsWith (@Nonnull final byte [] aArray, @Nonnegative final int nArrayOfs, @Nonnegative final int nArrayLen, @Nullable final byte [] aSearch, @Nonnegative final int nSearchOfs, @Nonnegative final int nSearchLen) { if (aSearch == null || nArrayLen <= 0 || nArrayLen < nSearchLen) return false; for (int i = 0; i < nSearchLen; i++) if (aArray[nArrayOfs + i] != aSearch[nSearchOfs + i]) return false; return true; } public static boolean startsWith (@Nonnull final char [] aArray, @Nullable final char [] aSearch) { if (aSearch == null) return false; return startsWith (aArray, 0, aArray.length, aSearch, 0, aSearch.length); } public static boolean startsWith (@Nonnull final char [] aArray, @Nonnegative final int nArrayLen, @Nullable final char [] aSearch) { if (aSearch == null) return false; return startsWith (aArray, 0, nArrayLen, aSearch, 0, aSearch.length); } public static boolean startsWith (@Nonnull final char [] aArray, @Nullable final char [] aSearch, @Nonnegative final int nSearchOfs, @Nonnegative final int nSearchLen) { return startsWith (aArray, 0, aArray.length, aSearch, nSearchOfs, nSearchLen); } public static boolean startsWith (@Nonnull final char [] aArray, @Nonnegative final int nArrayLen, @Nullable final char [] aSearch, @Nonnegative final int nSearchOfs, @Nonnegative final int nSearchLen) { return startsWith (aArray, 0, nArrayLen, aSearch, nSearchOfs, nSearchLen); } public static boolean startsWith (@Nonnull final char [] aArray, @Nonnegative final int nArrayOfs, @Nonnegative final int nArrayLen, @Nullable final char [] aSearch, @Nonnegative final int nSearchOfs, @Nonnegative final int nSearchLen) { if (aSearch == null || nArrayLen <= 0 || nArrayLen < nSearchLen) return false; for (int i = 0; i < nSearchLen; i++) if (aArray[nArrayOfs + i] != aSearch[nSearchOfs + i]) return false; return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy