/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package com.github.geophile.erdo.util; import com.github.geophile.erdo.memorymonitor.MemoryTracker; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; public class IntArray implements Iterable<Integer>, MemoryTracker.Trackable<IntArray> { // MemoryTracker.Trackable interface public long sizeBytes() { return arrays.size() * ARRAY_CAPACITY * 4; } // Iterable interface // TODO: Get rid of this. It forces lots of Integer generation public Iterator<Integer> iterator() { return new IntArrayIterator(); } // IntArray interface public int at(int position) { try { return arrays.get(position / ARRAY_CAPACITY)[position % ARRAY_CAPACITY]; } catch (IndexOutOfBoundsException e) { throw new IndexOutOfBoundsException(String.format("arrays.size: %s, position: %s", arrays == null ? null : arrays.size(), position)); } } public void at(int position, int value) { try { arrays.get(position / ARRAY_CAPACITY)[position % ARRAY_CAPACITY] = value; } catch (IndexOutOfBoundsException e) { throw new IndexOutOfBoundsException(String.format("arrays.size: %s, position: %s", arrays == null ? null : arrays.size(), position)); } } public void append(int x) { ensureArray(); currentArray[currentArrayPosition++] = x; count++; } public int size() { return count; } public IntArray(MemoryTracker<IntArray> memoryTracker) { this.memoryTracker = memoryTracker; } // For use by this class private void ensureArray() { if (currentArrayPosition == ARRAY_CAPACITY) { currentArray = null; } if (currentArray == null) { currentArray = new int[ARRAY_CAPACITY]; arrays.add(currentArray); currentArrayPosition = 0; if (memoryTracker != null) { memoryTracker.track(arrays.size() * ARRAY_CAPACITY * 4); } } } // Class state private final static int ARRAY_CAPACITY = 1000; // Object state private final MemoryTracker<IntArray> memoryTracker; private final List<int[]> arrays = new ArrayList<int[]>(); private int[] currentArray; // Last element of arrays, and the arrays array currently being loaded. private int currentArrayPosition; private int count = 0; // Inner classes private class IntArrayIterator implements Iterator<Integer> { public boolean hasNext() { return position < count; } public Integer next() { Integer next; if (position >= count) { throw new NoSuchElementException(); } next = at(position++); return next; } public void remove() { throw new UnsupportedOperationException(); } private int position = 0; } }