Mercurial > hg4j
diff src/org/tmatesoft/hg/internal/IntMap.java @ 276:6355ecda1f08
Tailored Map implementation with int keys
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Mon, 29 Aug 2011 22:15:12 +0200 |
parents | |
children | 55fad5e0e98b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/tmatesoft/hg/internal/IntMap.java Mon Aug 29 22:15:12 2011 +0200 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2011 TMate Software Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For information on how to redistribute this software under + * the terms of a license other than GNU General Public License + * contact TMate Software at support@hg4j.com + */ +package org.tmatesoft.hg.internal; + +import java.util.NoSuchElementException; + + +/** + * Map implementation that uses plain int keys and performs with log n effectiveness. + * + * @author Artem Tikhomirov + * @author TMate Software Ltd. + */ +public class IntMap<V> { + + private int[] keys; + private Object[] values; + private int size; + + public IntMap(int size) { + keys = new int[size <= 0 ? 16 : size]; + values = new Object[keys.length]; + } + + public int size() { + return size; + } + + public int firstKey() { + if (size == 0) { + throw new NoSuchElementException(); + } + return keys[0]; + } + + public int lastKey() { + if (size == 0) { + throw new NoSuchElementException(); + } + return keys[size-1]; + } + + public void trimToSize() { + if (size < keys.length) { + int[] newKeys = new int[size]; + Object[] newValues = new Object[size]; + System.arraycopy(keys, 0, newKeys, 0, size); + System.arraycopy(values, 0, newValues, 0, size); + keys = newKeys; + values = newValues; + } + } + + public void put(int key, V value) { + int ix = binarySearch(keys, size, key); + if (ix < 0) { + final int insertPoint = -ix - 1; + assert insertPoint <= size; // can't be greater, provided binarySearch didn't malfunction. + if (size == keys.length) { + int newCapacity = size + (size >>> 2); + int[] newKeys = new int[newCapacity]; + Object[] newValues = new Object[newCapacity]; + System.arraycopy(keys, 0, newKeys, 0, insertPoint); + System.arraycopy(keys, insertPoint, newKeys, insertPoint+1, keys.length - insertPoint); + System.arraycopy(values, 0, newValues, 0, insertPoint); + System.arraycopy(values, insertPoint, newValues, insertPoint+1, values.length - insertPoint); + keys = newKeys; + values = newValues; + } else { + // arrays got enough capacity + if (insertPoint != size) { + System.arraycopy(keys, insertPoint, keys, insertPoint+1, keys.length - insertPoint - 1); + System.arraycopy(values, insertPoint, values, insertPoint+1, values.length - insertPoint - 1); + } + // else insertPoint is past known elements, no need to copy arrays + } + keys[insertPoint] = key; + values[insertPoint] = value; + size++; + } else { + values[ix] = value; + } + } + + public boolean containsKey(int key) { + return binarySearch(keys, size, key) >= 0; + } + + @SuppressWarnings("unchecked") + public V get(int key) { + int ix = binarySearch(keys, size, key); + if (ix >= 0) { + return (V) values[ix]; + } + return null; + } + + // copy of Arrays.binarySearch, with upper search limit as argument + private static int binarySearch(int[] a, int high, int key) { + int low = 0; + high--; + + while (low <= high) { + int mid = (low + high) >> 1; + int midVal = a[mid]; + + if (midVal < key) + low = mid + 1; + else if (midVal > key) + high = mid - 1; + else + return mid; // key found + } + return -(low + 1); // key not found. + } + + public static void main(String[] args) { + IntMap<String> m = new IntMap<String>(-1); + m.put(18, "18"); + m.put(1, "1"); + m.put(9, "9"); + m.put(20, "20"); + m.put(2, "2"); + m.put(3, "3"); + m.put(21, "21"); + m.put(15, "15"); + m.put(12, "12"); + m.put(11, "11"); + m.put(31, "31"); + System.out.printf("%d [%d..%d]\n", m.size(), m.firstKey(), m.lastKey()); + for (int i = m.firstKey(); i <= m.lastKey(); i++) { + if (m.containsKey(i)) { + System.out.printf("@%02d:%s\n", i, m.get(i)); + } + } + } +}