arrays.java
/*
* Java Genetic Algorithm Library (@__identifier__@).
* Copyright (c) @__year__@ Franz Wilhelmstötter
*
* 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.
*
* Author:
* Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
*/
package org.jenetics.util;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
/**
* Static helper methods concerning arrays.
*
* @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
* @since 1.0
* @version 1.5 — <em>$Date: 2014-02-15 $</em>
*/
public final class arrays extends StaticObject {
private arrays() {}
/**
* Unified method for calculating the hash code of every {@link Seq}
* implementation. The hash code is defined as followed:
*
* [code]
* int hashCode = 1;
* final Iterator<E> it = seq.iterator();
* while (it.hasNext()) {
* final E obj = it.next();
* hashCode = 31*hashCode + (obj == null ? 0 : obj.hashCode());
* }
* [/code]
*
* @see Seq#hashCode()
* @see List#hashCode()
*
* @param seq the sequence to calculate the hash code for.
* @return the hash code of the given sequence.
*/
public static int hashCode(final Seq<?> seq) {
int hash = 1;
for (Object element : seq) {
hash = 31*hash + (element == null ? 0: element.hashCode());
}
return hash;
}
/**
* Unified method for compare to sequences for equality.
*
* @see Seq#equals(Object)
*
* @param seq the sequence to test for equality.
* @param obj the object to test for equality with the sequence.
* @return {@code true} if the given objects are sequences and contain the
* same objects in the same order, {@code false} otherwise.
*/
public static boolean equals(final Seq<?> seq, final Object obj) {
if (obj == seq) {
return true;
}
if (!(obj instanceof Seq<?>)) {
return false;
}
final Seq<?> other = (Seq<?>)obj;
boolean equals = (seq.length() == other.length());
for (int i = seq.length(); equals && --i >= 0;) {
final Object element = seq.get(i);
if (element != null) {
equals = element.equals(other.get(i));
} else {
equals = other.get(i) == null;
}
}
return equals;
}
/**
* Swap two elements of an given list.
*
* @param <T> the list type.
* @param list the array
* @param i index of the first list element.
* @param j index of the second list element.
* @throws IndexOutOfBoundsException if <tt>i < 0</tt> or
* <tt>j < 0</tt> or <tt>i > a.length</tt> or
* <tt>j > a.length</tt>
* @throws NullPointerException if the give list is {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static <T> void swap(final List<T> list, final int i, final int j) {
final T old = list.get(i);
list.set(i, list.get(j));
list.set(j, old);
}
/**
* Swap two elements of an given array.
*
* @param <T> the array type.
* @param array the array
* @param i index of the first array element.
* @param j index of the second array element.
* @throws IndexOutOfBoundsException if <tt>i < 0</tt> or
* <tt>j < 0</tt> or <tt>i > a.length</tt> or
* <tt>j > a.length</tt>
* @throws NullPointerException if the give array is {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static <T> void swap(final T[] array, final int i, final int j) {
final T old = array[i];
array[i] = array[j];
array[j] = old;
}
/**
* Swap two byte elements of the given array.
*
* @param array the array
* @param i index of the first array element.
* @param j index of the second array element.
* @throws IndexOutOfBoundsException if <tt>i < 0</tt> or
* <tt>j < 0</tt> or <tt>i > a.length</tt> or
* <tt>j > a.length</tt>
* @throws NullPointerException if the give array is {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static void swap(final byte[] array, final int i, final int j) {
final byte old = array[i];
array[i] = array[j];
array[j] = old;
}
/**
* Swap two elements of an given array.
*
* @param array the array
* @param i index of the first array element.
* @param j index of the second array element.
* @throws IndexOutOfBoundsException if <tt>i < 0</tt> or
* <tt>j < 0</tt> or <tt>i > a.length</tt> or
* <tt>j > a.length</tt>
* @throws NullPointerException if the give array is {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static void swap(final int[] array, final int i, final int j) {
final int old = array[i];
array[i] = array[j];
array[j] = old;
}
/**
* Calls the sort method on the {@link Arrays} class.
*
* @throws NullPointerException if the give array is {@code null}.
* @throws UnsupportedOperationException if the array is sealed
* ({@code array.isSealed() == true}).
*/
public static <T extends Object & Comparable<? super T>> MSeq<T>
sort(final MSeq<T> array)
{
Collections.sort(array.asList());
return array;
}
/**
* Test whether the given array is sorted in ascending order.
*
* @param seq the array to test.
* @return {@code true} if the given {@code array} is sorted in ascending
* order, {@code false} otherwise.
* @throws NullPointerException if the given array or one of it's element is
* {@code null}.
*/
public static <T extends Object & Comparable<? super T>>
boolean isSorted(final Seq<T> seq)
{
boolean sorted = true;
for (int i = 0, n = seq.length() - 1; i < n && sorted; ++i) {
sorted = seq.get(i).compareTo(seq.get(i + 1)) <= 0;
}
return sorted;
}
/**
* Test whether the given array is sorted in ascending order. The order of
* the array elements is defined by the given comparator.
*
* @param seq the array to test.
* @param comparator the comparator which defines the order.
* @return {@code true} if the given {@code array} is sorted in ascending
* order, {@code false} otherwise.
* @throws NullPointerException if the given array or one of it's element or
* the comparator is {@code null}.
*/
public static <T> boolean isSorted(
final Seq<T> seq, final Comparator<? super T> comparator
) {
boolean sorted = true;
for (int i = 0, n = seq.length() - 1; i < n && sorted; ++i) {
sorted = comparator.compare(seq.get(i), seq.get(i + 1)) <= 0;
}
return sorted;
}
/**
* Randomize the {@code array} using the given {@link Random} object. The used
* shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
* Third edition, page 142, Algorithm S (Selection sampling technique).
*
* @param array the {@code array} to randomize.
* @throws NullPointerException if the give array is {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static <T> T[] shuffle(final T[] array) {
return shuffle(array, RandomRegistry.getRandom());
}
/**
* Randomize the {@code array} using the given {@link Random} object. The used
* shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
* Third edition, page 142, Algorithm S (Selection sampling technique).
*
* @param array the {@code array} to randomize.
* @param random the {@link Random} object to use for randomize.
* @param <T> the component type of the array to randomize.
* @throws NullPointerException if the give array or the random object is
* {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static <T> T[] shuffle(final T[] array, final Random random) {
for (int j = array.length - 1; j > 0; --j) {
swap(array, j, random.nextInt(j + 1));
}
return array;
}
/**
* Randomize the {@code array} using the given {@link Random} object. The used
* shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
* Third edition, page 142, Algorithm S (Selection sampling technique).
*
* @param array the {@code array} to randomize.
* @throws NullPointerException if the give array is {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static <T> MSeq<T> shuffle(final MSeq<T> array) {
return shuffle(array, RandomRegistry.getRandom());
}
/**
* Randomize the {@code array} using the given {@link Random} object. The used
* shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
* Third edition, page 142, Algorithm S (Selection sampling technique).
*
* @param array the {@code array} to randomize.
* @param random the {@link Random} object to use for randomize.
* @param <T> the component type of the array to randomize.
* @throws NullPointerException if the give array or the random object is
* {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static <T> MSeq<T> shuffle(final MSeq<T> array, final Random random) {
for (int j = array.length() - 1; j > 0; --j) {
array.swap(j, random.nextInt(j + 1));
}
return array;
}
/**
* Randomize the {@code list} using the given {@link Random} object. The used
* shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
* Third edition, page 142, Algorithm S (Selection sampling technique).
*
* @param list the {@code array} to randomize.
* @param <T> the component type of the array to randomize.
* @throws NullPointerException if the give list is {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static <T> void shuffle(final List<T> list) {
shuffle(list, RandomRegistry.getRandom());
}
/**
* Randomize the {@code list} using the given {@link Random} object. The used
* shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
* Third edition, page 142, Algorithm S (Selection sampling technique).
*
* @param list the {@code array} to randomize.
* @param random the {@link Random} object to use for randomize.
* @param <T> the component type of the array to randomize.
* @throws NullPointerException if the give list or the random object is
* {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static <T> void shuffle(final List<T> list, final Random random) {
for (int j = list.size() - 1; j > 0; --j) {
swap(list, j, random.nextInt(j + 1));
}
}
/**
* Randomize the {@code array} using the given {@link Random} object. The used
* shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
* Third edition, page 142, Algorithm S (Selection sampling technique).
*
* @param array the {@code array} to randomize.
* @throws NullPointerException if the give array is {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static void shuffle(final int[] array) {
shuffle(array, RandomRegistry.getRandom());
}
/**
* Randomize the {@code array} using the given {@link Random} object. The used
* shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
* Third edition, page 142, Algorithm S (Selection sampling technique).
*
* @param array the {@code array} to randomize.
* @param random the {@link Random} object to use for randomize.
* @throws NullPointerException if the give array or the random object is
* {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static void shuffle(final int[] array, final Random random) {
for (int j = array.length - 1; j > 0; --j) {
swap(array, j, random.nextInt(j + 1));
}
}
/**
* Reverses the part of the array determined by the to indexes.
*
* @param <T> the array type.
* @param array the array to reverse
* @param from the first index (inclusive)
* @param to the second index (exclusive)
* @throws IllegalArgumentException if <tt>from > to</tt>
* @throws IndexOutOfBoundsException if <tt>from < 0</tt> or
* <tt>to > a.length</tt>
* @throws NullPointerException if the give array is {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static <T> T[] reverse(final T[] array, final int from, final int to) {
rangeCheck(array.length, from, to);
int i = from;
int j = to;
while (i < j) {
swap(array, i++, --j);
}
return array;
}
/**
* Reverses the given array in place.
*
* @param <T> the array type.
* @param array the array to reverse.
* @throws NullPointerException if the give array is {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static <T> T[] reverse(final T[] array) {
return reverse(array, 0, array.length);
}
@Deprecated
static void reverse(final byte[] array) {
int i = 0;
int j = array.length;
while (i < j) {
_swap(array, i++, --j);
}
}
private static void _swap(final byte[] array, final int i, final int j) {
final byte old = array[i];
array[i] = array[j];
array[j] = old;
}
private static void rangeCheck(int length, int from, int to) {
if (from > to) {
throw new IllegalArgumentException(
"fromIndex(" + from + ") > toIndex(" + to+ ")"
);
}
if (from < 0) {
throw new ArrayIndexOutOfBoundsException(from);
}
if (to > length) {
throw new ArrayIndexOutOfBoundsException(to);
}
}
/**
* Return a array with the indexes of the partitions of an array with the
* given size. The length of the returned array is {@code min(size, prts) + 1}.
* <p/>
* Some examples:
* <pre>
* partition(10, 3): [0, 3, 6, 10]
* partition(15, 6): [0, 2, 4, 6, 9, 12, 15]
* partition(5, 10): [0, 1, 2, 3, 4, 5]
* </pre>
*
* The following examples prints the start index (inclusive) and the end
* index (exclusive) of the {@code partition(15, 6)}.
* [code]
* int[] parts = partition(15, 6);
* for (int i = 0; i < parts.length - 1; ++i) {
* System.out.println(i + ": " + parts[i] + "\t" + parts[i + 1]);
* }
* [/code]
* <pre>
* 0: 0 2
* 1: 2 4
* 2: 4 6
* 3: 6 9
* 4: 9 12
* 5: 12 15
* </pre>
*
* This example shows how this can be used in an concurrent environment:
* [code]
* try (final Concurrency c = Concurrency.start()) {
* final int[] parts = arrays.partition(population.size(), _maxThreads);
*
* for (int i = 0; i < parts.length - 1; ++i) {
* final int part = i;
* c.execute(new Runnable() { @Override public void run() {
* for (int j = parts[part + 1]; --j >= parts[part];) {
* population.get(j).evaluate();
* }
* }});
* }
* }
* [/code]
*
* @param size the size of the array to partition.
* @param parts the number of parts the (virtual) array should be partitioned.
* @return the partition array with the length of {@code min(size, parts) + 1}.
* @throws IllegalArgumentException if {@code size} or {@code p} is less than one.
*/
public static int[] partition(final int size, final int parts) {
if (size < 1) {
throw new IllegalArgumentException(
"Size must greater than zero: " + size
);
}
if (parts < 1) {
throw new IllegalArgumentException(
"Number of partitions must greater than zero: " + parts
);
}
final int pts = Math.min(size, parts);
final int[] partition = new int[pts + 1];
final int bulk = size/pts;
final int rest = size%pts;
assert ((bulk*pts + rest) == size);
for (int i = 0, n = pts - rest; i < n; ++i) {
partition[i] = i*bulk;
}
for (int i = 0, n = rest + 1; i < n; ++i) {
partition[pts - rest + i] = (pts - rest)*bulk + i*(bulk + 1);
}
return partition;
}
/**
* Selects a random subset of size {@code k} from a set of size {@code n}.
*
* @see #subset(int, int[])
*
* @param n the size of the set.
* @param k the size of the subset.
* @throws IllegalArgumentException if {@code n < k}, {@code k == 0} or if
* {@code n*k} will cause an integer overflow.
* @return the subset array.
*
* @deprecated Use {@link math#subset(int, int)} instead.
*/
@Deprecated
public static int[] subset(final int n, final int k) {
return math.subset(n, k);
}
/**
* Selects a random subset of size {@code k} from a set of size {@code n}.
*
* @see #subset(int, int[], Random)
*
* @param n the size of the set.
* @param k the size of the subset.
* @param random the random number generator used.
* @throws NullPointerException if {@code random} is {@code null}.
* @throws IllegalArgumentException if {@code n < k}, {@code k == 0} or if
* {@code n*k} will cause an integer overflow.
* @return the subset array.
*
* @deprecated Use {@link math#subset(int, int, Random)} instead.
*/
@Deprecated
public static int[] subset(final int n, final int k, final Random random) {
return math.subset(n, k, random);
}
/**
* <p>
* Selects a random subset of size {@code sub.length} from a set of size
* {@code n}.
* </p>
*
* <p>
* <em>Authors:</em>
* FORTRAN77 original version by Albert Nijenhuis, Herbert Wilf. This
* version based on the C++ version by John Burkardt.
* </p>
*
* <p><em><a href="https://people.scs.fsu.edu/~burkardt/c_src/subset/subset.html">
* Reference:</a></em>
* Albert Nijenhuis, Herbert Wilf,
* Combinatorial Algorithms for Computers and Calculators,
* Second Edition,
* Academic Press, 1978,
* ISBN: 0-12-519260-6,
* LC: QA164.N54.
* </p>
*
* @param n the size of the set.
* @param sub the sub set array.
* @throws NullPointerException if {@code sub} is {@code null}.
* @throws IllegalArgumentException if {@code n < sub.length},
* {@code sub.length == 0} or {@code n*sub.length} will cause an
* integer overflow.
*
* @deprecated Use {@link math#subset(int, int[])} instead.
*/
@Deprecated
public static void subset(final int n, final int sub[]) {
math.subset(n, sub);
}
/**
* <p>
* Selects a random subset of size {@code sub.length} from a set of size
* {@code n}.
* </p>
*
* <p>
* <em>Authors:</em>
* FORTRAN77 original version by Albert Nijenhuis, Herbert Wilf. This
* version based on the C++ version by John Burkardt.
* </p>
*
* <p><em><a href="https://people.scs.fsu.edu/~burkardt/c_src/subset/subset.html">
* Reference:</a></em>
* Albert Nijenhuis, Herbert Wilf,
* Combinatorial Algorithms for Computers and Calculators,
* Second Edition,
* Academic Press, 1978,
* ISBN: 0-12-519260-6,
* LC: QA164.N54.
* </p>
*
* @param n the size of the set.
* @param sub the sub set array.
* @param random the random number generator used.
* @throws NullPointerException if {@code sub} or {@code random} is
* {@code null}.
* @throws IllegalArgumentException if {@code n < sub.length},
* {@code sub.length == 0} or {@code n*sub.length} will cause an
* integer overflow.
*
* @deprecated Use {@link math#subset(int, int[], Random)} instead.
*/
@Deprecated
public static int[] subset(final int n, final int sub[], final Random random) {
return math.subset(n, sub, random);
}
/**
* Calculates a random permutation.
*
* @param p the permutation array.
* @throws NullPointerException if the permutation array is {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static int[] permutation(final int[] p) {
return permutation(p, RandomRegistry.getRandom());
}
/**
* Calculates a random permutation.
*
* @param p the permutation array.
* @param random the random number generator.
* @throws NullPointerException if the permutation array or the random number
* generator is {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static int[] permutation(final int[] p, final Random random) {
requireNonNull(p, "Permutation array");
requireNonNull(random, "Random");
for (int i = 0; i < p.length; ++i) {
p[i] = i;
}
shuffle(p, random);
return p;
}
/**
* Calculates the permutation with the given {@code rank}.
*
* <p>
* <em>Authors:</em>
* FORTRAN77 original version by Albert Nijenhuis, Herbert Wilf. This
* version based on the C++ version by John Burkardt.
* </p>
*
* <p><em><a href="https://people.scs.fsu.edu/~burkardt/c_src/subset/subset.html">
* Reference:</a></em>
* Albert Nijenhuis, Herbert Wilf,
* Combinatorial Algorithms for Computers and Calculators,
* Second Edition,
* Academic Press, 1978,
* ISBN: 0-12-519260-6,
* LC: QA164.N54.
* </p>
*
* @param p the permutation array.
* @param rank the permutation rank.
* @throws NullPointerException it the permutation array is {@code null}.
* @throws IllegalArgumentException if {@code rank < 1}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static int[] permutation(final int[] p, final long rank) {
requireNonNull(p, "Permutation array");
if (rank < 1) {
throw new IllegalArgumentException(format(
"Rank smaler than 1: %s", rank
));
}
Arrays.fill(p, 0);
long jrank = rank - 1;
for (int i = 1; i <= p.length; ++i) {
int iprev = p.length + 1 - i;
int irem = (int)(jrank%iprev);
jrank = jrank/iprev;
int j = 0;
int jdir = 0;
if ((jrank%2) == 1) {
j = 0;
jdir = 1;
} else {
j = p.length + 1;
jdir = -1;
}
int icount = 0;
do {
j = j + jdir;
if (p[j - 1] == 0) {
++icount;
}
} while (irem >= icount);
p[j - 1] = iprev;
}
return p;
}
/**
* Returns the index of the first occurrence of the specified element in
* the {@code array}, or -1 if the {@code array} does not contain the element.
* @param array the array to search.
* @param start the start index of the search.
* @param element the element to search for.
* @return the index of the first occurrence of the specified element in the
* given {@code array}, of -1 if the {@code array} does not contain
* the element.
* @throws NullPointerException if the given {@code array} is {@code null}.
* @throws IndexOutOfBoundsException for an illegal end point index value
* (start < 0 || end > length || start > end)
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static int indexOf(
final Object[] array, final int start, final int end,
final Object element
) {
requireNonNull(array, "Array");
if (start < 0 || end > array.length || start > end) {
throw new IndexOutOfBoundsException(format(
"Invalid index range: [%d, %s]", start, end
));
}
int index = -1;
if (element != null) {
for (int i = start; i < end && index == -1; ++i) {
if (element.equals(array[i])) {
index = i;
}
}
} else {
for (int i = start; i < end && index == -1; ++i) {
if (array[i] == null) {
index = i;
}
}
}
return index;
}
/**
* Returns the index of the first occurrence of the specified element in
* the {@code array}, or -1 if the {@code array} does not contain the element.
* @param array the array to search.
* @param element the element to search for.
* @return the index of the first occurrence of the specified element in the
* given {@code array}, of -1 if the {@code array} does not contain
* the element.
* @throws NullPointerException if the given {@code array} is {@code null}.
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static int indexOf(final Object[] array, final Object element) {
return indexOf(array, 0, array.length, element);
}
/**
* @see #indexOf(Object[], Object)
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static <T> int indexWhere(
final T[] array,
final Function<? super T, Boolean> predicate
) {
requireNonNull(array, "Array");
requireNonNull(predicate, "Predicate");
int index = -1;
for (int i = 0; i < array.length && index == -1; ++i) {
if (predicate.apply(array[i])) {
index = i;
}
}
return index;
}
/**
* @see #indexOf(Object[], Object)
*
* @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
*/
@Deprecated
public static <T> int indexWhere(
final Iterable<? extends T> values,
final Function<? super T, Boolean> predicate
) {
requireNonNull(values, "Array");
requireNonNull(predicate, "Predicate");
int index = -1;
int i = 0;
for (Iterator<? extends T>
it = values.iterator(); it.hasNext() && index == -1; ++i)
{
if (predicate.apply(it.next())) {
index = i;
}
}
return index;
}
/**
* @deprecated Align the naming with the upcomming JDK 1.8 release. Use
* {@link #forEach(Object[], Function)} instead.
*/
@Deprecated
public static <T, R> void foreach(
final T[] array,
final Function<? super T, ? extends R> f
) {
forEach(array, f);
}
/**
* Iterates over all elements of the given {@code array} as long as the
* {@code predicate} returns {@code true} (which means <i>continue</i>) and
* returns the index the iteration has been interrupted. -1 is returned if
* all elements were visited.
* <p/>
* Can be used to check all array elements for nullness.
*
* [code]
* public void foo(final Integer[] values) {
* arrays.forEach(values, new Validator.NonNull());
* ...
* }
* [/code]
*
* @param array the array to iterate.
* @param f the function to apply to every element.
* @throws NullPointerException if one of the elements are {@code null}.
*/
public static <T, R> void forEach(
final T[] array,
final Function<? super T, ? extends R> f
) {
requireNonNull(array, "Array");
requireNonNull(f, "Predicate");
for (int i = 0; i < array.length; ++i) {
f.apply(array[i]);
}
}
/**
* @deprecated Align the naming with the upcoming JDK 1.8 release. Use
* {@link #forEach(Iterable, Function)} instead.
*/
@Deprecated
public static <T, R> void foreach(
final Iterable<? extends T> values,
final Function<? super T, ? extends R> f
) {
forEach(values, f);
}
/**
* Iterates over all elements of the given {@code values}
*
* @param values the values to iterate.
* @param f the function to apply to each element.
* @throws NullPointerException if one of the elements are {@code null}.
*/
public static <T, R> void forEach(
final Iterable<? extends T> values,
final Function<? super T, ? extends R> f
) {
requireNonNull(values, "Array");
requireNonNull(f, "Function");
for (final T value : values) {
f.apply(value);
}
}
/**
* Map the array from type A to an other array of type B.
*
* @param <A> the source type.
* @param <B> the target type.
* @param a the source array.
* @param b the target array. If the given array is to short a new array
* with the right size is created, mapped and returned. If the given
* array is long enough <i>this</i> array is returned.
* @param converter the converter needed for mapping from type A to type B.
* @return the mapped array. If {@code b} is long enough {@code b} is
* returned otherwise a new created array.
* @throws NullPointerException if one of the arguments is {@code null}.
*/
public static <A, B> B[] map(
final A[] a,
final B[] b,
final Function<? super A, ? extends B> converter
) {
requireNonNull(a, "Source array");
requireNonNull(b, "Target array");
requireNonNull(converter, "Converter");
B[] result = b;
if (b.length < a.length) {
@SuppressWarnings("unchecked")
final B[] r = (B[])java.lang.reflect.Array.newInstance(
b.getClass().getComponentType(), a.length
);
result = r;
}
for (int i = 0; i < result.length; ++i) {
result[i] = converter.apply(a[i]);
}
return result;
}
}