/** * This software is licensed to you under the Apache License, Version 2.0 (the * "Apache License"). * * LinkedIn's contributions are made under the Apache License. If you contribute * to the Software, the contributions will be deemed to have been made under the * Apache License, unless you expressly indicate otherwise. Please do not make any * contributions that would be inconsistent with the Apache License. * * You may obtain a copy of the Apache License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, this software * distributed under the Apache License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Apache * License for the specific language governing permissions and limitations for the * software governed under the Apache License. * * © 2012 LinkedIn Corp. All Rights Reserved. */ package com.senseidb.indexing.activity.time; import java.util.Arrays; /** * A copy on write int array wrapper, optimized to store activity updates * @author vzhabiuk * */ public class IntContainer { private static int[] EMPTY_ARR = new int[0]; private static final int initialGrowthFactor = 2; private static final int capacityThreshold = 10; protected int[] array; protected int startIndex = 0; protected int actualSize = 0; public IntContainer(int capacity) { if (capacity == 0) { array = EMPTY_ARR; } else { array = new int[capacity]; } } public IntContainer() { array = new int[1]; } public int removeFirst() { ensureCapacityOnStart(); if (actualSize == 0) { throw new IllegalStateException("The collection is empty"); } startIndex++; actualSize--; return array[startIndex - 1]; } public int removeLast() { ensureCapacityOnStart(); if (actualSize == 0) { throw new IllegalStateException("The collection is empty"); } actualSize--; return array[startIndex + actualSize]; } public int getSize() { return actualSize; } public int peekFirst() { return array[startIndex]; } public int peekLast() { return array[startIndex + actualSize - 1]; } public int get(int index) { return array[startIndex + index]; } public IntContainer add(int number) { ensureCapacityOnEnd(); array[startIndex + actualSize] = number; actualSize++; return this; } private void ensureCapacityOnEnd() { if (actualSize + startIndex < array.length) { return; } double growthFactor = 1.2; int newSize = array.length < capacityThreshold ? array.length + initialGrowthFactor : (int) (array.length * growthFactor); int[] oldArr = array; array = new int[newSize]; System.arraycopy(oldArr, startIndex, array, 0, actualSize); startIndex = 0; } private void ensureCapacityOnStart() { int newStartIndex = startIndex; int newArrayLength = array.length; int reduceFactor = 2; if (actualSize >= capacityThreshold && startIndex > actualSize / (reduceFactor * reduceFactor)) { newStartIndex = 0; } else if (startIndex > reduceFactor && actualSize < capacityThreshold) { newStartIndex = 0; } if (array.length > reduceFactor && actualSize < array.length / reduceFactor) { newArrayLength = array.length / reduceFactor; } if (newStartIndex != startIndex || newArrayLength != array.length) { int[] oldArr = array; if (newArrayLength != array.length) { array = new int[newArrayLength]; } System.arraycopy(oldArr, startIndex, array, 0, actualSize); startIndex = 0; } } @Override public String toString() { return Arrays.toString(array); } public int size() { return actualSize; } }