/** * Copyright 2014 * * 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. * * @project loon * @author cping * @email:javachenpeng@yahoo.com * @version 0.4.2 */ package loon.utils.collection; import java.util.AbstractList; public class ArraySlice<T> extends AbstractList<T> { private final T[] array; private int left, right, start, stride; public T[] getArray() { return array; } public int getStart() { return start; } public int getLeft() { return left; } public int getRight() { return right; } public int getStride() { return stride; } public ArraySlice(T[] array) { this(array, 0, array.length); } public ArraySlice(T[] array, int start, int end) { this(array, start, end, start, 1); } public ArraySlice(T[] array, int left, int right, int start, int stride) { this.array = array; this.stride = stride; this.start = start = absoluteIndex(start, array.length); this.left = left = absoluteIndex(left, array.length); this.right = right = absoluteIndex(right, array.length); if (right < left) { throw new NegativeArraySizeException( "Trying to make a slice with left bound " + left + " and right bound" + right + "."); } if (left != right && (start < left || right <= start)) { throw new IndexOutOfBoundsException("Start of slice is at " + start + ", while the bounds are [" + left + ", " + right + "[."); } } private int absoluteIndex(int index, int size) { return (index < 0) ? (size + index) : (index); } @Override public int size() { return right - left; } private int index(int _index) { int index = _index; index = stride * index; index = absoluteIndex(index, size()); if (index < 0 || size() <= index) { throw new IndexOutOfBoundsException("index " + _index + " (stride: " + stride + ") in " + this.getClass().getName() + " instance of size " + size()); } return (start + index) % array.length; } @Override public T get(int index) { return array[index(index)]; } @Override public T set(int index, T element) { T out = get(index); array[index(index)] = element; return out; } public void shiftLeft() { start = (size() > 1) ? index(-1) : start; } public void shiftRight() { start = (size() > 1) ? index(1) : start; } public void shiftLeftBound() { if (left - 1 < 0) { throw new IndexOutOfBoundsException(); } left = left - 1; } public void shiftRightBound() { if (right > array.length) { throw new IndexOutOfBoundsException(); } right = right + 1; } public void growSlice() { if (right < array.length) { shiftRightBound(); } else if (left > 0) { shiftLeftBound(); } else { throw new IllegalStateException( "Trying to grow a slice that already occupies the whole array."); } } public void setStride(int stride) { this.stride = stride; } }