001 /*
002 * Java Genetic Algorithm Library (jenetics-5.2.0).
003 * Copyright (c) 2007-2020 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@gmail.com)
019 */
020 package io.jenetics.ext.internal;
021
022 import static java.lang.Math.max;
023 import static java.lang.String.format;
024 import static java.lang.System.arraycopy;
025 import static java.util.Arrays.copyOf;
026 import static java.util.Objects.requireNonNull;
027
028 import java.util.Arrays;
029 import java.util.function.IntConsumer;
030 import java.util.stream.IntStream;
031
032 /**
033 * Resizable-int array implementation
034 *
035 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
036 * @version 4.3
037 * @since 4.1
038 */
039 public final class IntList {
040
041 private static final int MAX_SIZE = Integer.MAX_VALUE - 8;
042 private static final int DEFAULT_CAPACITY = 10;
043 private static final int[] EMPTY_ARRAY = {};
044 private static final int[] DEFAULT_EMPTY_ARRAY = {};
045
046 private int[] _data;
047 private int _size;
048
049 /**
050 * Constructs an empty list with the specified initial capacity.
051 *
052 * @param capacity the initial capacity of the list
053 * @throws IllegalArgumentException if the specified initial capacity
054 * is negative
055 */
056 public IntList(final int capacity) {
057 if (capacity > 0) {
058 _data = new int[capacity];
059 } else if (capacity == 0) {
060 _data = EMPTY_ARRAY;
061 } else {
062 throw new IllegalArgumentException("Illegal Capacity: "+ capacity);
063 }
064 }
065
066 /**
067 * Constructs an empty list with an initial capacity of ten.
068 */
069 public IntList() {
070 _data = DEFAULT_EMPTY_ARRAY;
071 }
072
073 /**
074 * Returns the element at the specified position in this list.
075 *
076 * @param index index of the element to return
077 * @return the element at the specified position in this list
078 * @throws IndexOutOfBoundsException if the index is out of range
079 * {@code (index < 0 || index > size())}
080 */
081 public int get(final int index) {
082 rangeCheck(index);
083
084 return _data[index];
085 }
086
087 /**
088 * Performs the given action for each element of the list.
089 *
090 * @param action the action to be performed for each element
091 * @throws NullPointerException if the specified action is {@code null}
092 */
093 public void forEach(final IntConsumer action) {
094 requireNonNull(action);
095
096 final int size = _size;
097 for (int i = 0; i < size; ++i) {
098 action.accept(_data[i]);
099 }
100 }
101
102 /**
103 * Returns a sequential {@link IntStream} with the specified list as its
104 * source.
105 *
106 * @return a sequential {@link IntStream}
107 */
108 public IntStream stream() {
109 return Arrays.stream(_data, 0, _size);
110 }
111
112 /**
113 * Appends the specified element to the end of this list.
114 *
115 * @param element element to be appended to this list
116 */
117 public void add(final int element) {
118 ensureSize(_size + 1);
119 _data[_size++] = element;
120 }
121
122 /**
123 * Inserts the specified element at the specified position in this list.
124 * Shifts the element currently at that position (if any) and any subsequent
125 * elements to the right (adds one to their indices).
126 *
127 * @param index index at which the specified element is to be inserted
128 * @param element element to be inserted
129 * @throws IndexOutOfBoundsException if the index is out of range
130 * {@code (index < 0 || index > size())}
131 */
132 public void add(final int index, final int element) {
133 addRangeCheck(index);
134
135 ensureSize(_size + 1);
136 arraycopy(
137 _data, index,
138 _data, index + 1,
139 _size - index
140 );
141 _data[index] = element;
142 _size++;
143 }
144
145 /**
146 * Appends all of the elements in the specified array to the end of this
147 * list.
148 *
149 * @param elements array containing elements to be added to this list
150 * @return <tt>true</tt> if this list changed as a result of the call
151 * @throws NullPointerException if the specified array is null
152 */
153 public boolean addAll(final int[] elements) {
154 final int count = elements.length;
155 ensureSize(_size + count);
156 arraycopy(elements, 0, _data, _size, count);
157 _size += count;
158
159 return count != 0;
160 }
161
162 /**
163 * Inserts all of the elements in the specified array into this list,
164 * starting at the specified position.
165 *
166 * @param index index at which to insert the first element from the
167 * specified collection
168 * @param elements collection containing elements to be added to this list
169 * @return <tt>true</tt> if this list changed as a result of the call
170 * @throws IndexOutOfBoundsException if the index is out of range
171 * {@code (index < 0 || index > size())}
172 * @throws NullPointerException if the specified array is null
173 */
174 public boolean addAll(final int index, final int[] elements) {
175 addRangeCheck(index);
176
177 final int count = elements.length;
178 ensureSize(_size + count);
179
180 final int moved = _size - index;
181 if (moved > 0) {
182 arraycopy(_data, index, _data, index + count, moved);
183 }
184
185 arraycopy(elements, 0, _data, index, count);
186 _size += count;
187 return count != 0;
188 }
189
190 /**
191 * Removes all of the elements from this list. The list will be empty after
192 * this call returns.
193 */
194 public void clear() {
195 _size = 0;
196 }
197
198 /**
199 * Trims the capacity of this <tt>ArrayList</tt> instance to be the list's
200 * current size. An application can use this operation to minimize the
201 * storage of an <tt>ArrayList</tt> instance.
202 */
203 public void trimToSize() {
204 if (_size < _data.length) {
205 _data = _size == 0
206 ? EMPTY_ARRAY
207 : copyOf(_data, _size);
208 }
209 }
210
211 /**
212 * Returns the number of elements in this list.
213 *
214 * @return the number of elements in this list
215 */
216 public int size() {
217 return _size;
218 }
219
220 /**
221 * Return {@code true} if the list is empty.
222 *
223 * @return {@code true} if the list is empty, {@code false} otherwise
224 */
225 public boolean isEmpty() {
226 return _size == 0;
227 }
228
229 /**
230 * Return the current elements as int array.
231 *
232 * @return the current elements as int array
233 */
234 public int[] toArray() {
235 return copyOf(_data, _size);
236 }
237
238 private void ensureSize(int size) {
239 ensureExplicitSize(capacity(_data, size));
240 }
241
242 private void ensureExplicitSize(int size) {
243 if (size - _data.length > 0) {
244 grow(size);
245 }
246 }
247
248 private void rangeCheck(final int index) {
249 if (index >= _size)
250 throw new IndexOutOfBoundsException(format(
251 "Index: %d, Size: %d", index, _size
252 ));
253 }
254
255 private void addRangeCheck(int index) {
256 if (index > _size || index < 0)
257 throw new IndexOutOfBoundsException(format(
258 "Index: %d, Size: %d", index, _size
259 ));
260 }
261
262 private static int capacity(final int[] data, final int capacity) {
263 if (data == DEFAULT_EMPTY_ARRAY) {
264 return max(DEFAULT_CAPACITY, capacity);
265 }
266 return capacity;
267 }
268
269 private void grow(final int size) {
270 final int oldSize = _data.length;
271
272 int newSize = oldSize + (oldSize >> 1);
273 if (newSize - size < 0) {
274 newSize = size;
275 }
276 if (newSize - MAX_SIZE > 0) {
277 newSize = hugeCapacity(size);
278 }
279
280 _data = copyOf(_data, newSize);
281 }
282
283 private static int hugeCapacity(final int minCapacity) {
284 if (minCapacity < 0) {
285 throw new OutOfMemoryError();
286 }
287
288 return minCapacity > MAX_SIZE
289 ? Integer.MAX_VALUE
290 : MAX_SIZE;
291 }
292
293 }
|