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

org.jenetics.util.MSeq Maven / Gradle / Ivy

There is a newer version: 3.6.0
Show newest version
/*
 * Java Genetic Algorithm Library (jenetics-3.1.0).
 * Copyright (c) 2007-2015 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 ([email protected])
 */
package org.jenetics.util;

import static java.lang.String.format;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Random;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;

import org.jenetics.internal.collection.ArrayProxyMSeq;
import org.jenetics.internal.collection.ObjectArrayProxy;

/**
 * Mutable, ordered, fixed sized sequence.
 *
 * 

* Implementation note: * This implementation is not thread safe. All {@link ISeq} and {@link MSeq} * instances created by {@link MSeq#toISeq} and {@link MSeq#subSeq(int)}, * respectively, must be protected by the same lock, when they are accessed * (get/set) by different threads. * * @see ISeq * * @author Franz Wilhelmstötter * @since 1.0 * @version 3.0 */ public interface MSeq extends Seq, Copyable> { /** * Set the {@code value} at the given {@code index}. * * @param index the index of the new value. * @param value the new value. * @throws IndexOutOfBoundsException if the index is out of range * (index < 0 || index >= size()). */ public void set(final int index, final T value); /** * Fills the sequence with values of the given iterator. * * @param it the iterator of the values to fill this sequence. * @return {@code this} sequence. */ public default MSeq setAll(final Iterator it) { for (int i = 0, n = length(); i < n && it.hasNext(); ++i) { set(i, it.next()); } return this; } /** * Fills the sequence with values of the given iterable. * * @param values the values to fill this sequence. * @return {@code this} sequence. */ public default MSeq setAll(final Iterable values) { setAll(values.iterator()); return this; } /** * Fill the sequence with the given values. * * @param values the first initial values of this sequence * @return {@code this} sequence. */ public default MSeq setAll(final T[] values) { for (int i = 0, n = length(); i < n && i < values.length; ++i) { set(i, values[i]); } return this; } /** * Fill the sequence with values generated by the given factory. * * @param supplier the value factory. * @return {@code this} sequence. * @throws NullPointerException if the given {@code factory} is {@code null}. */ public default MSeq fill(final Supplier supplier) { for (int i = 0, n = length(); i < n; ++i) { set(i, supplier.get()); } return this; } /** * Swap the elements at the two positions. * * @param i the index of the first element. * @param j the index of the second element. * @throws IndexOutOfBoundsException if {@code i < 0 || j >= length()}. */ public default void swap(final int i, final int j) { final T temp = get(i); set(i, get(j)); set(j, temp); } /** * Swap a given range with a range of the same size with another array. * *

	 *            start                end
	 *              |                   |
	 * this:  +---+---+---+---+---+---+---+---+---+---+---+---+
	 *              +---------------+
	 *                          +---------------+
	 * other: +---+---+---+---+---+---+---+---+---+---+---+---+
	 *                          |
	 *                      otherStart
	 * 
* * @param start the start index of {@code this} range, inclusively. * @param end the end index of {@code this} range, exclusively. * @param other the other array to swap the elements with. * @param otherStart the start index of the {@code other} array. * @throws IndexOutOfBoundsException if {@code start > end} or * if {@code start < 0 || end >= this.length() || otherStart < 0 || * otherStart + (end - start) >= other.length()} */ public default void swap( final int start, final int end, final MSeq other, final int otherStart ) { if (otherStart < 0 || (otherStart + (end - start)) > length()) { throw new ArrayIndexOutOfBoundsException(format( "Invalid index range: [%d, %d)", otherStart, (otherStart + (end - start)) )); } if (start < end) { for (int i = (end - start); --i >= 0;) { final T temp = get(start + i); set(start + i, other.get(otherStart + i)); other.set(otherStart + i, temp); } } } /** * Randomize the {@code array} using the {@link Random} object currently * registered in the {@link RandomRegistry} class. The used shuffling * algorithm is from D. Knuth TAOCP, Seminumerical Algorithms, Third edition, * page 142, Algorithm S (Selection sampling technique). * * @return this shuffled sequence */ public default MSeq shuffle() { return shuffle(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 random the {@link Random} object to use for randomize. * @return this shuffled sequence * @throws NullPointerException if the random object is {@code null}. */ public default MSeq shuffle(final Random random) { for (int j = length() - 1; j > 0; --j) { swap(j, random.nextInt(j + 1)); } return this; } /** * Returns a list iterator over the elements in this sequence (in proper * sequence). * * @return a list iterator over the elements in this list (in proper * sequence) */ public ListIterator listIterator(); @Override public MSeq subSeq(final int start, final int end); @Override public MSeq subSeq(final int start); @Override public MSeq map(final Function mapper); /** * Return a read-only projection of this sequence. Changes to the original * sequence will not influence the returned {@code ISeq}. * * @return a read-only projection of this sequence */ public ISeq toISeq(); /* ************************************************************************* * Some static factory methods. * ************************************************************************/ /** * Returns a {@code Collector} that accumulates the input elements into a * new {@code MSeq}. * * @param the type of the input elements * @return a {@code Collector} which collects all the input elements into a * {@code MSeq}, in encounter order */ public static Collector> toMSeq() { return Collector.of( (Supplier>)ArrayList::new, List::add, (left, right) -> { left.addAll(right); return left; }, MSeq::of ); } /** * Single instance of an empty {@code MSeq}. */ public static final MSeq EMPTY = ofLength(0); /** * Return an empty {@code MSeq}. * * @param the element type of the new {@code MSeq}. * @return an empty {@code MSeq}. */ @SuppressWarnings("unchecked") public static MSeq empty() { return (MSeq)EMPTY; } /** * Create a new {@code MSeq} with the given {@code length}. * * @param length the length of the created {@code MSeq}. * @param the element type of the new {@code MSeq}. * @return the new mutable sequence. */ public static MSeq ofLength(final int length) { return new ArrayProxyMSeq<>(new ObjectArrayProxy(length)); } /** * Create a new {@code MSeq} from the given values. * * @param the element type * @param values the array values. * @return a new {@code Meq} with the given values. * @throws NullPointerException if the {@code values} array is {@code null}. */ @SafeVarargs public static MSeq of(final T... values) { final ObjectArrayProxy proxy = new ObjectArrayProxy<>( values.clone(), 0, values.length ); return new ArrayProxyMSeq<>(proxy); } /** * Create a new {@code MSeq} from the given values. * * @param the element type * @param values the array values. * @return a new {@code MSeq} with the given values. * @throws NullPointerException if the {@code values} array is {@code null}. */ @SuppressWarnings("unchecked") public static MSeq of(final Iterable values) { MSeq mseq = null; if (values instanceof ISeq) { mseq = ((ISeq)values).copy(); } else if (values instanceof MSeq) { mseq = (MSeq)values; } else if (values instanceof Collection) { final Collection collection = (Collection)values; mseq = MSeq.ofLength(collection.size()).setAll(values); } else { int length = 0; for (final T value : values) ++length; mseq = MSeq.ofLength(length); int index = 0; for (final T value : values) mseq.set(index++, value); } return mseq; } /** * Create a new {@code MSeq} from the values of the given {@code Seq}. * * @param the element type * @param values the array values. * @return an new {@code MSeq} with the given values * @throws NullPointerException if the {@code values} array is {@code null}. */ public static MSeq of(final Seq values) { return values instanceof ArrayProxyMSeq ? ((ArrayProxyMSeq)values).copy() : MSeq.ofLength(values.length()).setAll(values); } }