1120 } 1121 1122 return value; 1123 } 1124 1125 /** 1126 * Save the state of the Hashtable to a stream (i.e., serialize it). 1127 * 1128 * @serialData The <i>capacity</i> of the Hashtable (the length of the 1129 * bucket array) is emitted (int), followed by the 1130 * <i>size</i> of the Hashtable (the number of key-value 1131 * mappings), followed by the key (Object) and value (Object) 1132 * for each key-value mapping represented by the Hashtable 1133 * The key-value mappings are emitted in no particular order. 1134 */ 1135 private void writeObject(java.io.ObjectOutputStream s) 1136 throws IOException { 1137 Entry<Object, Object> entryStack = null; 1138 1139 synchronized (this) { 1140 // Write out the length, threshold, loadfactor 1141 s.defaultWriteObject(); 1142 1143 // Write out length, count of elements 1144 s.writeInt(table.length); 1145 s.writeInt(count); 1146 1147 // Stack copies of the entries in the table 1148 for (Entry<?, ?> entry : table) { 1149 1150 while (entry != null) { 1151 entryStack = 1152 new Entry<>(0, entry.key, entry.value, entryStack); 1153 entry = entry.next; 1154 } 1155 } 1156 } 1157 1158 // Write out the key/value objects from the stacked entries 1159 while (entryStack != null) { 1160 s.writeObject(entryStack.key); 1161 s.writeObject(entryStack.value); 1162 entryStack = entryStack.next; 1163 } 1164 } 1165 1166 /** 1167 * Reconstitute the Hashtable from a stream (i.e., deserialize it). 1168 */ 1169 private void readObject(java.io.ObjectInputStream s) 1170 throws IOException, ClassNotFoundException 1171 { 1172 // Read in the length, threshold, and loadfactor 1173 s.defaultReadObject(); 1174 1175 // Read the original length of the array and number of elements 1176 int origlength = s.readInt(); 1177 int elements = s.readInt(); 1178 1179 // Compute new size with a bit of room 5% to grow but 1180 // no larger than the original size. Make the length 1181 // odd if it's large enough, this helps distribute the entries. 1182 // Guard against the length ending up zero, that's not valid. 1183 int length = (int)(elements * loadFactor) + (elements / 20) + 3; 1184 if (length > elements && (length & 1) == 0) 1185 length--; 1186 if (origlength > 0 && length > origlength) 1187 length = origlength; 1188 table = new Entry<?,?>[length]; 1189 threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1); 1190 count = 0; 1191 1192 // Read the number of elements and then all the key/value objects 1193 for (; elements > 0; elements--) { 1194 @SuppressWarnings("unchecked") 1195 K key = (K)s.readObject(); 1196 @SuppressWarnings("unchecked") 1197 V value = (V)s.readObject(); 1198 // synch could be eliminated for performance 1199 reconstitutionPut(table, key, value); 1200 } 1201 } 1202 1203 /** 1204 * The put method used by readObject. This is provided because put 1205 * is overridable and should not be called in readObject since the 1206 * subclass will not yet be initialized. 1207 * 1208 * <p>This differs from the regular put method in several ways. No 1209 * checking for rehashing is necessary since the number of elements 1210 * initially in the table is known. The modCount is not incremented 1211 * because we are creating a new instance. Also, no return value 1212 * is needed. 1213 */ 1214 private void reconstitutionPut(Entry<?,?>[] tab, K key, V value) 1215 throws StreamCorruptedException 1216 { 1217 if (value == null) { 1218 throw new java.io.StreamCorruptedException(); 1219 } 1220 // Makes sure the key is not already in the hashtable. 1221 // This should not happen in deserialized version. 1222 int hash = key.hashCode(); 1223 int index = (hash & 0x7FFFFFFF) % tab.length; 1224 for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) { 1225 if ((e.hash == hash) && e.key.equals(key)) { 1226 throw new java.io.StreamCorruptedException(); 1227 } 1228 } 1229 // Creates the new entry. 1230 @SuppressWarnings("unchecked") 1231 Entry<K,V> e = (Entry<K,V>)tab[index]; 1232 tab[index] = new Entry<>(hash, key, value, e); | 1120 } 1121 1122 return value; 1123 } 1124 1125 /** 1126 * Save the state of the Hashtable to a stream (i.e., serialize it). 1127 * 1128 * @serialData The <i>capacity</i> of the Hashtable (the length of the 1129 * bucket array) is emitted (int), followed by the 1130 * <i>size</i> of the Hashtable (the number of key-value 1131 * mappings), followed by the key (Object) and value (Object) 1132 * for each key-value mapping represented by the Hashtable 1133 * The key-value mappings are emitted in no particular order. 1134 */ 1135 private void writeObject(java.io.ObjectOutputStream s) 1136 throws IOException { 1137 Entry<Object, Object> entryStack = null; 1138 1139 synchronized (this) { 1140 // Write out the threshold and loadFactor 1141 s.defaultWriteObject(); 1142 1143 // Write out length and count of elements 1144 s.writeInt(table.length); 1145 s.writeInt(count); 1146 1147 // Stack copies of the entries in the table 1148 for (Entry<?, ?> entry : table) { 1149 1150 while (entry != null) { 1151 entryStack = 1152 new Entry<>(0, entry.key, entry.value, entryStack); 1153 entry = entry.next; 1154 } 1155 } 1156 } 1157 1158 // Write out the key/value objects from the stacked entries 1159 while (entryStack != null) { 1160 s.writeObject(entryStack.key); 1161 s.writeObject(entryStack.value); 1162 entryStack = entryStack.next; 1163 } 1164 } 1165 1166 /** 1167 * Reconstitute the Hashtable from a stream (i.e., deserialize it). 1168 */ 1169 private void readObject(java.io.ObjectInputStream s) 1170 throws IOException, ClassNotFoundException 1171 { 1172 // Read in the threshold and loadFactor 1173 s.defaultReadObject(); 1174 1175 // Read the original length of the array and number of elements 1176 int origlength = s.readInt(); 1177 int elements = s.readInt(); 1178 1179 // Compute new length with a bit of room 5% to grow but 1180 // no larger than the original length. Make the length 1181 // odd if it's large enough, this helps distribute the entries. 1182 // Guard against the length ending up zero, that's not valid. 1183 int length = (int)(elements / loadFactor) + (elements / 20) + 3; 1184 if (length > elements && (length & 1) == 0) 1185 length--; 1186 if (origlength > 0 && length > origlength) 1187 length = origlength; 1188 table = new Entry<?,?>[length]; 1189 threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1); 1190 count = 0; 1191 1192 // Read the number of elements and then all the key/value objects 1193 for (; elements > 0; elements--) { 1194 @SuppressWarnings("unchecked") 1195 K key = (K)s.readObject(); 1196 @SuppressWarnings("unchecked") 1197 V value = (V)s.readObject(); 1198 // sync is eliminated for performance 1199 reconstitutionPut(table, key, value); 1200 } 1201 } 1202 1203 /** 1204 * The put method used by readObject. This is provided because put 1205 * is overridable and should not be called in readObject since the 1206 * subclass will not yet be initialized. 1207 * 1208 * <p>This differs from the regular put method in several ways. No 1209 * checking for rehashing is necessary since the number of elements 1210 * initially in the table is known. The modCount is not incremented and 1211 * there's no synchronization because we are creating a new instance. 1212 * Also, no return value is needed. 1213 */ 1214 private void reconstitutionPut(Entry<?,?>[] tab, K key, V value) 1215 throws StreamCorruptedException 1216 { 1217 if (value == null) { 1218 throw new java.io.StreamCorruptedException(); 1219 } 1220 // Makes sure the key is not already in the hashtable. 1221 // This should not happen in deserialized version. 1222 int hash = key.hashCode(); 1223 int index = (hash & 0x7FFFFFFF) % tab.length; 1224 for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) { 1225 if ((e.hash == hash) && e.key.equals(key)) { 1226 throw new java.io.StreamCorruptedException(); 1227 } 1228 } 1229 // Creates the new entry. 1230 @SuppressWarnings("unchecked") 1231 Entry<K,V> e = (Entry<K,V>)tab[index]; 1232 tab[index] = new Entry<>(hash, key, value, e); |