arrays.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-2.0.2).
003  * Copyright (c) 2007-2014 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * You may obtain a copy of the License at
008  *
009  *      http://www.apache.org/licenses/LICENSE-2.0
010  *
011  * Unless required by applicable law or agreed to in writing, software
012  * distributed under the License is distributed on an "AS IS" BASIS,
013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  * See the License for the specific language governing permissions and
015  * limitations under the License.
016  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019  */
020 package org.jenetics.util;
021 
022 import static java.util.Objects.requireNonNull;
023 
024 import java.util.Arrays;
025 import java.util.Collections;
026 import java.util.Comparator;
027 import java.util.List;
028 
029 /**
030  * Static helper methods concerning arrays.
031  *
032  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
033  @since 1.0
034  @version 2.0 &mdash; <em>$Date: 2014-03-31 $</em>
035  */
036 public final class arrays extends StaticObject {
037     private arrays() {}
038 
039 
040     /**
041      * Unified method for calculating the hash code of every {@link Seq}
042      * implementation. The hash code is defined as followed:
043      *
044      * [code]
045      * int hashCode = 1;
046      * final Iterator&lt;E&gt; it = seq.iterator();
047      * while (it.hasNext()) {
048      *     final E obj = it.next();
049      *     hashCode = 31*hashCode + (obj == null ? 0 : obj.hashCode());
050      * }
051      * [/code]
052      *
053      @see Seq#hashCode()
054      @see List#hashCode()
055      *
056      @param seq the sequence to calculate the hash code for.
057      @return the hash code of the given sequence.
058      */
059     public static int hashCode(final Seq<?> seq) {
060         int hash = 1;
061         for (Object element : seq) {
062             hash = 31*hash + (element == null 0: element.hashCode());
063         }
064         return hash;
065     }
066 
067     /**
068      * Unified method for compare to sequences for equality.
069      *
070      @see Seq#equals(Object)
071      *
072      @param seq the sequence to test for equality.
073      @param obj the object to test for equality with the sequence.
074      @return {@code true} if the given objects are sequences and contain the
075      *          same objects in the same order, {@code false} otherwise.
076      */
077     public static boolean equals(final Seq<?> seq, final Object obj) {
078         if (obj == seq) {
079             return true;
080         }
081         if (!(obj instanceof Seq<?>)) {
082             return false;
083         }
084 
085         final Seq<?> other = (Seq<?>)obj;
086         boolean equals = (seq.length() == other.length());
087         for (int i = seq.length(); equals && --i >= 0;) {
088             final Object element = seq.get(i);
089             if (element != null) {
090                 equals = element.equals(other.get(i));
091             else {
092                 equals = other.get(i== null;
093             }
094         }
095         return equals;
096     }
097 
098     /**
099      * Calls the sort method on the {@link Arrays} class.
100      *
101      @param <T> the array element type
102      @param array the array to sort
103      @return the sorted input array, for command chaining
104      @throws NullPointerException if the give array is {@code null}.
105      @throws UnsupportedOperationException if the array is sealed
106      *           ({@code array.isSealed() == true}).
107      */
108     public static <T extends Object & Comparable<? super T>> MSeq<T>
109     sort(final MSeq<T> array)
110     {
111         Collections.sort(array.asList());
112         return array;
113     }
114 
115     /**
116      * Test whether the given array is sorted in ascending order.
117      *
118      @param <T> the array element type
119      @param seq the array to test.
120      @return {@code true} if the given {@code array} is sorted in ascending
121      *         order, {@code false} otherwise.
122      @throws NullPointerException if the given array or one of it's element is
123      *         {@code null}.
124      */
125     public static <T extends Object & Comparable<? super T>>
126     boolean isSorted(final Seq<T> seq)
127     {
128         boolean sorted = true;
129         for (int i = 0, n = seq.length() 1; i < n && sorted; ++i) {
130             sorted = seq.get(i).compareTo(seq.get(i + 1)) <= 0;
131         }
132 
133         return sorted;
134     }
135 
136     /**
137      * Test whether the given array is sorted in ascending order. The order of
138      * the array elements is defined by the given comparator.
139      *
140      @param <T> the array element type
141      @param seq the array to test.
142      @param comparator the comparator which defines the order.
143      @return {@code true} if the given {@code array} is sorted in ascending
144      *         order, {@code false} otherwise.
145      @throws NullPointerException if the given array or one of it's element or
146      *         the comparator is {@code null}.
147      */
148     public static <T> boolean isSorted(
149         final Seq<T> seq, final Comparator<? super T> comparator
150     ) {
151         boolean sorted = true;
152         for (int i = 0, n = seq.length() 1; i < n && sorted; ++i) {
153             sorted = comparator.compare(seq.get(i), seq.get(i + 1)) <= 0;
154         }
155 
156         return sorted;
157     }
158 
159     /**
160      * Return a array with the indexes of the partitions of an array with the
161      * given size. The length of the returned array is {@code min(size, prts) + 1}.
162      <p>
163      * Some examples:
164      <pre>
165      *      partition(10, 3): [0, 3, 6, 10]
166      *      partition(15, 6): [0, 2, 4, 6, 9, 12, 15]
167      *      partition(5, 10): [0, 1, 2, 3, 4, 5]
168      </pre>
169      *
170      * The following examples prints the start index (inclusive) and the end
171      * index (exclusive) of the {@code partition(15, 6)}.
172      * [code]
173      * int[] parts = partition(15, 6);
174      * for (int i = 0; i &lt; parts.length - 1; ++i) {
175      *     System.out.println(i + ": " + parts[i] + "\t" + parts[i + 1]);
176      * }
177      * [/code]
178      <pre>
179      *      0: 0     2
180      *      1: 2     4
181      *      2: 4     6
182      *      3: 6     9
183      *      4: 9     12
184      *      5: 12    15
185      </pre>
186      *
187      * This example shows how this can be used in an concurrent environment:
188      * [code]
189      * try (final Concurrency c = Concurrency.start()) {
190      *     final int[] parts = arrays.partition(population.size(), _maxThreads);
191      *
192      *     for (int i = 0; i &lt; parts.length - 1; ++i) {
193      *         final int part = i;
194      *         c.execute(new Runnable() { @Override public void run() {
195      *             for (int j = parts[part + 1]; --j &gt;= parts[part];) {
196      *                 population.get(j).evaluate();
197      *             }
198      *         }});
199      *     }
200      * }
201      * [/code]
202      *
203      @param size the size of the array to partition.
204      @param parts the number of parts the (virtual) array should be partitioned.
205      @return the partition array with the length of {@code min(size, parts) + 1}.
206      @throws IllegalArgumentException if {@code size} or {@code p} is less than one.
207      */
208     public static int[] partition(final int size, final int parts) {
209         if (size < 1) {
210             throw new IllegalArgumentException(
211                 "Size must greater than zero: " + size
212             );
213         }
214         if (parts < 1) {
215             throw new IllegalArgumentException(
216                 "Number of partitions must greater than zero: " + parts
217             );
218         }
219 
220         final int pts = Math.min(size, parts);
221         final int[] partition = new int[pts + 1];
222 
223         final int bulk = size/pts;
224         final int rest = size%pts;
225         assert ((bulk*pts + rest== size);
226 
227         for (int i = 0, n = pts - rest; i < n; ++i) {
228             partition[i= i*bulk;
229         }
230         for (int i = 0, n = rest + 1; i < n; ++i) {
231             partition[pts - rest + i(pts - rest)*bulk + i*(bulk + 1);
232         }
233 
234         return partition;
235     }
236 
237     /**
238      * Iterates over all elements of the given {@code array} as long as the
239      * {@code predicate} returns {@code true} (which means <i>continue</i>) and
240      * returns the index the iteration has been interrupted. -1 is returned if
241      * all elements were visited.
242      <p>
243      * Can be used to check all array elements for nullness.
244      *
245      * [code]
246      * public void foo(final Integer[] values) {
247      *     arrays.forEach(values, new Validator.NonNull());
248      *     ...
249      * }
250      * [/code]
251      *
252      @param <T> the array element type
253      @param <R> the returned type of the applied function
254      @param array the array to iterate.
255      @param f the function to apply to every element.
256      @throws NullPointerException if one of the elements are {@code null}.
257      */
258     public static <T, R> void forEach(
259         final T[] array,
260         final Function<? super T, ? extends R> f
261     ) {
262         requireNonNull(array, "Array");
263         requireNonNull(f, "Predicate");
264 
265         for (int i = 0; i < array.length; ++i) {
266             f.apply(array[i]);
267         }
268     }
269 
270     /**
271      * Iterates over all elements of the given {@code values}
272      *
273      @param <T> the element type
274      @param <R> the returned type of the applied function
275      @param values the values to iterate.
276      @param f the function to apply to each element.
277      @throws NullPointerException if one of the elements are {@code null}.
278      */
279     public static <T, R> void forEach(
280         final Iterable<? extends T> values,
281         final Function<? super T, ? extends R> f
282     ) {
283         requireNonNull(values, "Array");
284         requireNonNull(f, "Function");
285 
286         for (final T value : values) {
287             f.apply(value);
288         }
289     }
290 
291     /**
292      * Map the array from type A to an other array of type B.
293      *
294      @param <A> the source type.
295      @param <B> the target type.
296      @param a the source array.
297      @param b the target array. If the given array is to short a new array
298      *        with the right size is created, mapped and returned. If the given
299      *        array is long enough <i>this</i> array is returned.
300      @param converter the converter needed for mapping from type A to type B.
301      @return the mapped array. If {@code b} is long enough {@code b} is
302      *         returned otherwise a new created array.
303      @throws NullPointerException if one of the arguments is {@code null}.
304      */
305     public static <A, B> B[] map(
306         final A[] a,
307         final B[] b,
308         final Function<? super A, ? extends B> converter
309     ) {
310         requireNonNull(a, "Source array");
311         requireNonNull(b, "Target array");
312         requireNonNull(converter, "Converter");
313 
314         B[] result = b;
315         if (b.length < a.length) {
316             @SuppressWarnings("unchecked")
317             final B[] r = (B[])java.lang.reflect.Array.newInstance(
318                 b.getClass().getComponentType(), a.length
319             );
320             result = r;
321         }
322 
323         for (int i = 0; i < result.length; ++i) {
324             result[i= converter.apply(a[i]);
325         }
326 
327         return result;
328     }
329 
330 }