ArrayMSeq.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-3.5.0).
003  * Copyright (c) 2007-2016 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.internal.collection;
021 
022 import static java.lang.Math.min;
023 import static java.lang.String.format;
024 
025 import java.util.Iterator;
026 import java.util.ListIterator;
027 import java.util.Random;
028 import java.util.function.Function;
029 import java.util.function.Supplier;
030 
031 import org.jenetics.util.ISeq;
032 import org.jenetics.util.MSeq;
033 
034 /**
035  * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
036  * @since 1.4
037  * @version 3.4
038  */
039 public class ArrayMSeq<T> extends ArraySeq<T> implements MSeq<T> {
040     private static final long serialVersionUID = 1L;
041 
042     public ArrayMSeq(final Array<T> array) {
043         super(array);
044     }
045 
046     @Override
047     public MSeq<T> copy() {
048         return isEmpty()
049             ? this
050             : new ArrayMSeq<>(array.copy());
051     }
052 
053     @Override
054     public Iterator<T> iterator() {
055         return listIterator();
056     }
057 
058     @Override
059     public ListIterator<T> listIterator() {
060         return new ArrayMIterator<>(array);
061     }
062 
063     @Override
064     public void set(final int index, final T value) {
065         array.set(index, value);
066     }
067 
068     @Override
069     public MSeq<T> setAll(final Iterator<? extends T> it) {
070         for (int i = 0; i < array.length() && it.hasNext(); ++i) {
071             array.set(i, it.next());
072         }
073         return this;
074     }
075 
076     @Override
077     public MSeq<T> setAll(final Iterable<? extends T> values) {
078         return setAll(values.iterator());
079     }
080 
081     @Override
082     public MSeq<T> setAll(final T[] values) {
083         for (int i = 0, n = min(array.length(), values.length); i < n; ++i) {
084             array.set(i, values[i]);
085         }
086         return this;
087     }
088 
089     public MSeq<T> fill(final Supplier<? extends T> supplier) {
090         for (int i = 0; i < array.length(); ++i) {
091             array.set(i, supplier.get());
092         }
093         return this;
094     }
095 
096     @Override
097     public MSeq<T> shuffle(final Random random) {
098         for (int j = length() - 1; j > 0; --j) {
099             swap(j, random.nextInt(j + 1));
100         }
101         return this;
102     }
103 
104     @Override
105     public void swap(final int i, final int j) {
106         final T temp = array.get(i);
107         array.set(i, array.get(j));
108         array.set(j, temp);
109     }
110 
111     @Override
112     @SuppressWarnings("unchecked")
113     public void swap(int start, int end, MSeq<T> other, int otherStart) {
114         checkIndex(start, end, otherStart, other.length());
115 
116         if (start < end) {
117             for (int i = end - start; --i >= 0;) {
118                 final T temp = array.get(i + start);
119                 array.set(i + start, other.get(otherStart + i));
120                 other.set(otherStart + i, temp);
121             }
122         }
123     }
124 
125     protected void checkIndex(
126         final int start, final int end,
127         final int otherStart, final int otherLength
128     ) {
129         array.checkIndex(start, end);
130         if (otherStart < 0 || (otherStart + (end - start)) > otherLength) {
131             throw new ArrayIndexOutOfBoundsException(format(
132                 "Invalid index range: [%d, %d)",
133                 otherStart, otherStart + end - start
134             ));
135         }
136     }
137 
138     @Override
139     public MSeq<T> subSeq(final int start, final int end) {
140         if (start > end) {
141             throw new ArrayIndexOutOfBoundsException(format(
142                 "start[%d] > end[%d]", start, end
143             ));
144         }
145         if (start < 0 || end > length()) {
146             throw new ArrayIndexOutOfBoundsException(format(
147                 "Indexes (%d, %d) range: [%d..%d)", start, end, 0, length()
148             ));
149         }
150 
151         return start == end
152             ? Empty.mseq()
153             : new ArrayMSeq<>(array.slice(start, end));
154     }
155 
156     @Override
157     public MSeq<T> subSeq(final int start) {
158         if (start < 0 || start > length()) {
159             throw new ArrayIndexOutOfBoundsException(format(
160                 "Index %d range: [%d..%d)", start, 0, length()
161             ));
162         }
163 
164         return start == length()
165             ? Empty.mseq()
166             : new ArrayMSeq<>(array.slice(start, length()));
167     }
168 
169     @Override
170     public <B> MSeq<B> map(final Function<? super T, ? extends B> mapper) {
171         final Array<B> mapped = Array.ofLength(length());
172         for (int i = 0; i < length(); ++i) {
173             mapped.set(i, mapper.apply(array.get(i)));
174         }
175         return new ArrayMSeq<>(mapped);
176     }
177 
178     @Override
179     public MSeq<T> append(final Iterable<? extends T> values) {
180         return new ArrayMSeq<>(__append(values));
181     }
182 
183     @Override
184     public MSeq<T> prepend(final Iterable<? extends T> values) {
185         return new ArrayMSeq<>(__prepend(values));
186     }
187 
188     @Override
189     public ISeq<T> toISeq() {
190         return isEmpty()
191             ? Empty.iseq()
192             : new ArrayISeq<>(array.seal());
193     }
194 
195 }