1 /******************************************************************************* 2 * Copyright (c) 2000, 2009 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.jdt.internal.compiler.util; 15 16 /** 17 * Hashtable of {Object --> int[] } 18 */ 19 public final class HashtableOfObjectToIntArray implements Cloneable { 20 21 // to avoid using Enumerations, walk the individual tables skipping nulls 22 public Object[] keyTable; 23 public int[][] valueTable; 24 25 public int elementSize; // number of elements in the table 26 int threshold; 27 HashtableOfObjectToIntArray()28 public HashtableOfObjectToIntArray() { 29 this(13); 30 } 31 HashtableOfObjectToIntArray(int size)32 public HashtableOfObjectToIntArray(int size) { 33 34 this.elementSize = 0; 35 this.threshold = size; // size represents the expected number of elements 36 int extraRoom = (int) (size * 1.75f); 37 if (this.threshold == extraRoom) 38 extraRoom++; 39 this.keyTable = new Object[extraRoom]; 40 this.valueTable = new int[extraRoom][]; 41 } 42 43 @Override clone()44 public Object clone() throws CloneNotSupportedException { 45 HashtableOfObjectToIntArray result = (HashtableOfObjectToIntArray) super.clone(); 46 result.elementSize = this.elementSize; 47 result.threshold = this.threshold; 48 49 int length = this.keyTable.length; 50 result.keyTable = new Object[length]; 51 System.arraycopy(this.keyTable, 0, result.keyTable, 0, length); 52 53 length = this.valueTable.length; 54 result.valueTable = new int[length][]; 55 System.arraycopy(this.valueTable, 0, result.valueTable, 0, length); 56 return result; 57 } 58 containsKey(Object key)59 public boolean containsKey(Object key) { 60 int length = this.keyTable.length, 61 index = (key.hashCode()& 0x7FFFFFFF) % length; 62 Object currentKey; 63 while ((currentKey = this.keyTable[index]) != null) { 64 if (currentKey.equals(key)) 65 return true; 66 if (++index == length) { 67 index = 0; 68 } 69 } 70 return false; 71 } 72 get(Object key)73 public int[] get(Object key) { 74 int length = this.keyTable.length, 75 index = (key.hashCode()& 0x7FFFFFFF) % length; 76 Object currentKey; 77 while ((currentKey = this.keyTable[index]) != null) { 78 if (currentKey.equals(key)) 79 return this.valueTable[index]; 80 if (++index == length) { 81 index = 0; 82 } 83 } 84 return null; 85 } 86 keysToArray(Object[] array)87 public void keysToArray(Object[] array) { 88 int index = 0; 89 for (int i=0, length=this.keyTable.length; i<length; i++) { 90 if (this.keyTable[i] != null) 91 array[index++] = this.keyTable[i]; 92 } 93 } 94 put(Object key, int[] value)95 public int[] put(Object key, int[] value) { 96 int length = this.keyTable.length, 97 index = (key.hashCode()& 0x7FFFFFFF) % length; 98 Object currentKey; 99 while ((currentKey = this.keyTable[index]) != null) { 100 if (currentKey.equals(key)) 101 return this.valueTable[index] = value; 102 if (++index == length) { 103 index = 0; 104 } 105 } 106 this.keyTable[index] = key; 107 this.valueTable[index] = value; 108 109 // assumes the threshold is never equal to the size of the table 110 if (++this.elementSize > this.threshold) 111 rehash(); 112 return value; 113 } 114 removeKey(Object key)115 public int[] removeKey(Object key) { 116 int length = this.keyTable.length, 117 index = (key.hashCode()& 0x7FFFFFFF) % length; 118 Object currentKey; 119 while ((currentKey = this.keyTable[index]) != null) { 120 if (currentKey.equals(key)) { 121 int[] value = this.valueTable[index]; 122 this.elementSize--; 123 this.keyTable[index] = null; 124 rehash(); 125 return value; 126 } 127 if (++index == length) { 128 index = 0; 129 } 130 } 131 return null; 132 } 133 rehash()134 private void rehash() { 135 136 HashtableOfObjectToIntArray newHashtable = new HashtableOfObjectToIntArray(this.elementSize * 2); // double the number of expected elements 137 Object currentKey; 138 for (int i = this.keyTable.length; --i >= 0;) 139 if ((currentKey = this.keyTable[i]) != null) 140 newHashtable.put(currentKey, this.valueTable[i]); 141 142 this.keyTable = newHashtable.keyTable; 143 this.valueTable = newHashtable.valueTable; 144 this.threshold = newHashtable.threshold; 145 } 146 size()147 public int size() { 148 return this.elementSize; 149 } 150 151 @Override toString()152 public String toString() { 153 StringBuffer buffer = new StringBuffer(); 154 Object key; 155 for (int i = 0, length = this.keyTable.length; i < length; i++) { 156 if ((key = this.keyTable[i]) != null) { 157 buffer.append(key).append(" -> "); //$NON-NLS-1$ 158 int[] ints = this.valueTable[i]; 159 buffer.append('['); 160 if (ints != null) { 161 for (int j = 0, max = ints.length; j < max; j++) { 162 if (j > 0) { 163 buffer.append(','); 164 } 165 buffer.append(ints[j]); 166 } 167 } 168 buffer.append("]\n"); //$NON-NLS-1$ 169 } 170 } 171 return String.valueOf(buffer); 172 } 173 } 174