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 — <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<E> 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 < 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 < 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 >= 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 }
|