Mercurial > hg4j
comparison 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 |
comparison
equal
deleted
inserted
replaced
275:6d1804fe0ed7 | 276:6355ecda1f08 |
---|---|
1 /* | |
2 * Copyright (c) 2011 TMate Software Ltd | |
3 * | |
4 * This program is free software; you can redistribute it and/or modify | |
5 * it under the terms of the GNU General Public License as published by | |
6 * the Free Software Foundation; version 2 of the License. | |
7 * | |
8 * This program is distributed in the hope that it will be useful, | |
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 * GNU General Public License for more details. | |
12 * | |
13 * For information on how to redistribute this software under | |
14 * the terms of a license other than GNU General Public License | |
15 * contact TMate Software at support@hg4j.com | |
16 */ | |
17 package org.tmatesoft.hg.internal; | |
18 | |
19 import java.util.NoSuchElementException; | |
20 | |
21 | |
22 /** | |
23 * Map implementation that uses plain int keys and performs with log n effectiveness. | |
24 * | |
25 * @author Artem Tikhomirov | |
26 * @author TMate Software Ltd. | |
27 */ | |
28 public class IntMap<V> { | |
29 | |
30 private int[] keys; | |
31 private Object[] values; | |
32 private int size; | |
33 | |
34 public IntMap(int size) { | |
35 keys = new int[size <= 0 ? 16 : size]; | |
36 values = new Object[keys.length]; | |
37 } | |
38 | |
39 public int size() { | |
40 return size; | |
41 } | |
42 | |
43 public int firstKey() { | |
44 if (size == 0) { | |
45 throw new NoSuchElementException(); | |
46 } | |
47 return keys[0]; | |
48 } | |
49 | |
50 public int lastKey() { | |
51 if (size == 0) { | |
52 throw new NoSuchElementException(); | |
53 } | |
54 return keys[size-1]; | |
55 } | |
56 | |
57 public void trimToSize() { | |
58 if (size < keys.length) { | |
59 int[] newKeys = new int[size]; | |
60 Object[] newValues = new Object[size]; | |
61 System.arraycopy(keys, 0, newKeys, 0, size); | |
62 System.arraycopy(values, 0, newValues, 0, size); | |
63 keys = newKeys; | |
64 values = newValues; | |
65 } | |
66 } | |
67 | |
68 public void put(int key, V value) { | |
69 int ix = binarySearch(keys, size, key); | |
70 if (ix < 0) { | |
71 final int insertPoint = -ix - 1; | |
72 assert insertPoint <= size; // can't be greater, provided binarySearch didn't malfunction. | |
73 if (size == keys.length) { | |
74 int newCapacity = size + (size >>> 2); | |
75 int[] newKeys = new int[newCapacity]; | |
76 Object[] newValues = new Object[newCapacity]; | |
77 System.arraycopy(keys, 0, newKeys, 0, insertPoint); | |
78 System.arraycopy(keys, insertPoint, newKeys, insertPoint+1, keys.length - insertPoint); | |
79 System.arraycopy(values, 0, newValues, 0, insertPoint); | |
80 System.arraycopy(values, insertPoint, newValues, insertPoint+1, values.length - insertPoint); | |
81 keys = newKeys; | |
82 values = newValues; | |
83 } else { | |
84 // arrays got enough capacity | |
85 if (insertPoint != size) { | |
86 System.arraycopy(keys, insertPoint, keys, insertPoint+1, keys.length - insertPoint - 1); | |
87 System.arraycopy(values, insertPoint, values, insertPoint+1, values.length - insertPoint - 1); | |
88 } | |
89 // else insertPoint is past known elements, no need to copy arrays | |
90 } | |
91 keys[insertPoint] = key; | |
92 values[insertPoint] = value; | |
93 size++; | |
94 } else { | |
95 values[ix] = value; | |
96 } | |
97 } | |
98 | |
99 public boolean containsKey(int key) { | |
100 return binarySearch(keys, size, key) >= 0; | |
101 } | |
102 | |
103 @SuppressWarnings("unchecked") | |
104 public V get(int key) { | |
105 int ix = binarySearch(keys, size, key); | |
106 if (ix >= 0) { | |
107 return (V) values[ix]; | |
108 } | |
109 return null; | |
110 } | |
111 | |
112 // copy of Arrays.binarySearch, with upper search limit as argument | |
113 private static int binarySearch(int[] a, int high, int key) { | |
114 int low = 0; | |
115 high--; | |
116 | |
117 while (low <= high) { | |
118 int mid = (low + high) >> 1; | |
119 int midVal = a[mid]; | |
120 | |
121 if (midVal < key) | |
122 low = mid + 1; | |
123 else if (midVal > key) | |
124 high = mid - 1; | |
125 else | |
126 return mid; // key found | |
127 } | |
128 return -(low + 1); // key not found. | |
129 } | |
130 | |
131 public static void main(String[] args) { | |
132 IntMap<String> m = new IntMap<String>(-1); | |
133 m.put(18, "18"); | |
134 m.put(1, "1"); | |
135 m.put(9, "9"); | |
136 m.put(20, "20"); | |
137 m.put(2, "2"); | |
138 m.put(3, "3"); | |
139 m.put(21, "21"); | |
140 m.put(15, "15"); | |
141 m.put(12, "12"); | |
142 m.put(11, "11"); | |
143 m.put(31, "31"); | |
144 System.out.printf("%d [%d..%d]\n", m.size(), m.firstKey(), m.lastKey()); | |
145 for (int i = m.firstKey(); i <= m.lastKey(); i++) { | |
146 if (m.containsKey(i)) { | |
147 System.out.printf("@%02d:%s\n", i, m.get(i)); | |
148 } | |
149 } | |
150 } | |
151 } |