1 18 package org.apache.batik.util; 19 20 import java.lang.ref.ReferenceQueue ; 21 import java.lang.ref.SoftReference ; 22 23 30 public class SoftDoublyIndexedTable { 31 32 35 protected final static int INITIAL_CAPACITY = 11; 36 37 40 protected Entry[] table; 41 42 45 protected int count; 46 47 50 protected ReferenceQueue referenceQueue = new ReferenceQueue (); 51 52 55 public SoftDoublyIndexedTable() { 56 table = new Entry[INITIAL_CAPACITY]; 57 } 58 59 63 public SoftDoublyIndexedTable(int c) { 64 table = new Entry[c]; 65 } 66 67 70 public int size() { 71 return count; 72 } 73 74 78 public Object get(Object o1, Object o2) { 79 int hash = hashCode(o1, o2) & 0x7FFFFFFF; 80 int index = hash % table.length; 81 82 for (Entry e = table[index]; e != null; e = e.next) { 83 if ((e.hash == hash) && e.match(o1, o2)) { 84 return e.get(); 85 } 86 } 87 return null; 88 } 89 90 94 public Object put(Object o1, Object o2, Object value) { 95 removeClearedEntries(); 96 97 int hash = hashCode(o1, o2) & 0x7FFFFFFF; 98 int index = hash % table.length; 99 100 Entry e = table[index]; 101 if (e != null) { 102 if ((e.hash == hash) && e.match(o1, o2)) { 103 Object old = e.get(); 104 table[index] = new Entry(hash, o1, o2, value, e.next); 105 return old; 106 } 107 Entry o = e; 108 e = e.next; 109 while (e != null) { 110 if ((e.hash == hash) && e.match(o1, o2)) { 111 Object old = e.get(); 112 e = new Entry(hash, o1, o2, value, e.next); 113 o.next = e; 114 return old; 115 } 116 117 o = e; 118 e = e.next; 119 } 120 } 121 122 int len = table.length; 124 if (count++ >= (len * 3) >>> 2) { 125 rehash(); 126 index = hash % table.length; 127 } 128 129 table[index] = new Entry(hash, o1, o2, value, table[index]); 130 return null; 131 } 132 133 136 public void clear() { 137 table = new Entry[INITIAL_CAPACITY]; 138 count = 0; 139 referenceQueue = new ReferenceQueue (); 140 } 141 142 145 protected void rehash () { 146 Entry[] oldTable = table; 147 148 table = new Entry[oldTable.length * 2 + 1]; 149 150 for (int i = oldTable.length-1; i >= 0; i--) { 151 for (Entry old = oldTable[i]; old != null;) { 152 Entry e = old; 153 old = old.next; 154 155 int index = e.hash % table.length; 156 e.next = table[index]; 157 table[index] = e; 158 } 159 } 160 } 161 162 165 protected int hashCode(Object o1, Object o2) { 166 int result = (o1 == null) ? 0 : o1.hashCode(); 167 return result ^ ((o2 == null) ? 0 : o2.hashCode()); 168 } 169 170 173 protected void removeClearedEntries() { 174 Entry e; 175 while ((e = (Entry)referenceQueue.poll()) != null) { 176 int index = e.hash % table.length; 177 Entry t = table[index]; 178 if (t == e) { 179 table[index] = e.next; 180 } else { 181 loop: for (;t!=null;) { 182 Entry c = t.next; 183 if (c == e) { 184 t.next = e.next; 185 break loop; 186 } 187 t = c; 188 } 189 } 190 count--; 191 } 192 } 193 194 197 protected class Entry extends SoftReference { 198 199 202 public int hash; 203 204 207 public Object key1; 208 209 212 public Object key2; 213 214 217 public Entry next; 218 219 222 public Entry(int hash, Object key1, Object key2, Object value, Entry next) { 223 super(value, referenceQueue); 224 this.hash = hash; 225 this.key1 = key1; 226 this.key2 = key2; 227 this.next = next; 228 } 229 230 233 public boolean match(Object o1, Object o2) { 234 if (key1 != null) { 235 if (!key1.equals(o1)) { 236 return false; 237 } 238 } else if (o1 != null) { 239 return false; 240 } 241 if (key2 != null) { 242 return key2.equals(o2); 243 } 244 return o2 == null; 245 } 246 } 247 } 248 | Popular Tags |