< prev index next >

src/java.base/share/classes/java/util/Hashtable.java

Print this page




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 the 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         // Validate loadFactor (ignore threshold - it will be re-computed)
1176         if (loadFactor <= 0 || Float.isNaN(loadFactor))
1177             throw new StreamCorruptedException("Illegal Load: " + loadFactor);
1178 
1179         // Read the original length of the array and number of elements
1180         int origlength = s.readInt();
1181         int elements = s.readInt();
1182 
1183         // Validate # of elements
1184         if (elements < 0)
1185             throw new StreamCorruptedException("Illegal # of Elements: " + elements);
1186 
1187         // Clamp original length to be more than elements / loadFactor
1188         // (this is the invariant enforced with auto-growth)
1189         origlength = Math.max(origlength, (int)(elements / loadFactor) + 1);
1190 
1191         // Compute new length with a bit of room 5% + 3 to grow but
1192         // no larger than the clamped original length.  Make the length
1193         // odd if it's large enough, this helps distribute the entries.
1194         // Guard against the length ending up zero, that's not valid.
1195         int length = (int)((elements + elements / 20) / loadFactor) + 3;
1196         if (length > elements && (length & 1) == 0)
1197             length--;
1198         length = Math.min(length, origlength);

1199         table = new Entry<?,?>[length];
1200         threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
1201         count = 0;
1202 
1203         // Read the number of elements and then all the key/value objects
1204         for (; elements > 0; elements--) {
1205             @SuppressWarnings("unchecked")
1206                 K key = (K)s.readObject();
1207             @SuppressWarnings("unchecked")
1208                 V value = (V)s.readObject();
1209             // sync is eliminated for performance
1210             reconstitutionPut(table, key, value);
1211         }
1212     }
1213 
1214     /**
1215      * The put method used by readObject. This is provided because put
1216      * is overridable and should not be called in readObject since the
1217      * subclass will not yet be initialized.
1218      *
1219      * <p>This differs from the regular put method in several ways. No
1220      * checking for rehashing is necessary since the number of elements
1221      * initially in the table is known. The modCount is not incremented and
1222      * there's no synchronization because we are creating a new instance.
1223      * Also, no return value is needed.
1224      */
1225     private void reconstitutionPut(Entry<?,?>[] tab, K key, V value)
1226         throws StreamCorruptedException
1227     {
1228         if (value == null) {
1229             throw new java.io.StreamCorruptedException();
1230         }
1231         // Makes sure the key is not already in the hashtable.
1232         // This should not happen in deserialized version.
1233         int hash = key.hashCode();
1234         int index = (hash & 0x7FFFFFFF) % tab.length;
1235         for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
1236             if ((e.hash == hash) && e.key.equals(key)) {
1237                 throw new java.io.StreamCorruptedException();
1238             }
1239         }
1240         // Creates the new entry.
1241         @SuppressWarnings("unchecked")
1242             Entry<K,V> e = (Entry<K,V>)tab[index];
1243         tab[index] = new Entry<>(hash, key, value, e);


< prev index next >