< 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 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);


< prev index next >