401 @Override 402 public int size() { 403 return e1 != null ? 2 : 1; 404 } 405 406 @Override 407 public boolean isEmpty() { 408 return false; 409 } 410 411 @Override 412 public E get(int index) { 413 if (index == 0) { 414 return e0; 415 } else if (index == 1 && e1 != null) { 416 return e1; 417 } 418 throw outOfBounds(index); 419 } 420 421 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 422 throw new InvalidObjectException("not serial proxy"); 423 } 424 425 private Object writeReplace() { 426 if (e1 == null) { 427 return new CollSer(CollSer.IMM_LIST, e0); 428 } else { 429 return new CollSer(CollSer.IMM_LIST, e0, e1); 430 } 431 } 432 433 @Override 434 public Object[] toArray() { 435 if (e1 == null) { 436 return new Object[] { e0 }; 437 } else { 438 return new Object[] { e0, e1 }; 439 } 440 } 441 442 @Override 443 @SuppressWarnings("unchecked") 444 public <T> T[] toArray(T[] a) { 481 tmp[i] = Objects.requireNonNull(input[i]); 482 } 483 elements = tmp; 484 } 485 486 @Override 487 public boolean isEmpty() { 488 return elements.length == 0; 489 } 490 491 @Override 492 public int size() { 493 return elements.length; 494 } 495 496 @Override 497 public E get(int index) { 498 return elements[index]; 499 } 500 501 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 502 throw new InvalidObjectException("not serial proxy"); 503 } 504 505 private Object writeReplace() { 506 return new CollSer(CollSer.IMM_LIST, elements); 507 } 508 509 @Override 510 public Object[] toArray() { 511 return Arrays.copyOf(elements, elements.length); 512 } 513 514 @Override 515 @SuppressWarnings("unchecked") 516 public <T> T[] toArray(T[] a) { 517 int size = elements.length; 518 if (a.length < size) { 519 // Make a new array of a's runtime type, but my contents: 520 return (T[]) Arrays.copyOf(elements, size, a.getClass()); 521 } 522 System.arraycopy(elements, 0, a, 0, size); 523 if (a.length > size) { 524 a[size] = null; // null-terminate 606 @Override 607 public boolean hasNext() { 608 return idx > 0; 609 } 610 611 @Override 612 public E next() { 613 if (idx == 1) { 614 idx = 0; 615 return SALT >= 0 || e1 == null ? e0 : e1; 616 } else if (idx == 2) { 617 idx = 1; 618 return SALT >= 0 ? e1 : e0; 619 } else { 620 throw new NoSuchElementException(); 621 } 622 } 623 }; 624 } 625 626 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 627 throw new InvalidObjectException("not serial proxy"); 628 } 629 630 private Object writeReplace() { 631 if (e1 == null) { 632 return new CollSer(CollSer.IMM_SET, e0); 633 } else { 634 return new CollSer(CollSer.IMM_SET, e0, e1); 635 } 636 } 637 638 @Override 639 public Object[] toArray() { 640 if (e1 == null) { 641 return new Object[] { e0 }; 642 } else if (SALT >= 0) { 643 return new Object[] { e1, e0 }; 644 } else { 645 return new Object[] { e0, e1 }; 646 } 647 } 648 649 @Override 789 } 790 791 // returns index at which element is present; or if absent, 792 // (-i - 1) where i is location where element should be inserted. 793 // Callers are relying on this method to perform an implicit nullcheck 794 // of pe 795 private int probe(Object pe) { 796 int idx = Math.floorMod(pe.hashCode(), elements.length); 797 while (true) { 798 E ee = elements[idx]; 799 if (ee == null) { 800 return -idx - 1; 801 } else if (pe.equals(ee)) { 802 return idx; 803 } else if (++idx == elements.length) { 804 idx = 0; 805 } 806 } 807 } 808 809 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 810 throw new InvalidObjectException("not serial proxy"); 811 } 812 813 private Object writeReplace() { 814 Object[] array = new Object[size]; 815 int dest = 0; 816 for (Object o : elements) { 817 if (o != null) { 818 array[dest++] = o; 819 } 820 } 821 return new CollSer(CollSer.IMM_SET, array); 822 } 823 824 @Override 825 public Object[] toArray() { 826 Object[] array = new Object[size]; 827 Iterator<E> it = iterator(); 828 for (int i = 0; i < size; i++) { 829 array[i] = it.next(); 830 } 831 return array; 832 } 889 @Override 890 public boolean containsKey(Object o) { 891 return o.equals(k0); // implicit nullcheck of o 892 } 893 894 @Override 895 public boolean containsValue(Object o) { 896 return o.equals(v0); // implicit nullcheck of o 897 } 898 899 @Override 900 public int size() { 901 return 1; 902 } 903 904 @Override 905 public boolean isEmpty() { 906 return false; 907 } 908 909 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 910 throw new InvalidObjectException("not serial proxy"); 911 } 912 913 private Object writeReplace() { 914 return new CollSer(CollSer.IMM_MAP, k0, v0); 915 } 916 917 @Override 918 public int hashCode() { 919 return k0.hashCode() ^ v0.hashCode(); 920 } 921 } 922 923 /** 924 * An array-based Map implementation. There is a single array "table" that 925 * contains keys and values interleaved: table[0] is kA, table[1] is vA, 926 * table[2] is kB, table[3] is vB, etc. The table size must be even. It must 927 * also be strictly larger than the size (the number of key-value pairs contained 928 * in the map) so that at least one null key is always present. 929 * @param <K> the key type 930 * @param <V> the value type 931 */ 932 static final class MapN<K,V> extends AbstractImmutableMap<K,V> { 1093 1094 // returns index at which the probe key is present; or if absent, 1095 // (-i - 1) where i is location where element should be inserted. 1096 // Callers are relying on this method to perform an implicit nullcheck 1097 // of pk. 1098 private int probe(Object pk) { 1099 int idx = Math.floorMod(pk.hashCode(), table.length >> 1) << 1; 1100 while (true) { 1101 @SuppressWarnings("unchecked") 1102 K ek = (K)table[idx]; 1103 if (ek == null) { 1104 return -idx - 1; 1105 } else if (pk.equals(ek)) { 1106 return idx; 1107 } else if ((idx += 2) == table.length) { 1108 idx = 0; 1109 } 1110 } 1111 } 1112 1113 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 1114 throw new InvalidObjectException("not serial proxy"); 1115 } 1116 1117 private Object writeReplace() { 1118 Object[] array = new Object[2 * size]; 1119 int len = table.length; 1120 int dest = 0; 1121 for (int i = 0; i < len; i += 2) { 1122 if (table[i] != null) { 1123 array[dest++] = table[i]; 1124 array[dest++] = table[i+1]; 1125 } 1126 } 1127 return new CollSer(CollSer.IMM_MAP, array); 1128 } 1129 } 1130 } 1131 1132 // ---------- Serialization Proxy ---------- 1133 1134 /** 1135 * A unified serialization proxy class for the immutable collections. 1136 * 1137 * @serial 1138 * @since 9 1139 */ 1140 final class CollSer implements Serializable { 1141 private static final long serialVersionUID = 6309168927139932177L; 1142 1143 static final int IMM_LIST = 1; 1144 static final int IMM_SET = 2; 1145 static final int IMM_MAP = 3; 1146 1147 /** 1148 * Indicates the type of collection that is serialized. 1149 * The low order 8 bits have the value 1 for an immutable 1150 * {@code List}, 2 for an immutable {@code Set}, and 3 for 1151 * an immutable {@code Map}. Any other value causes an 1152 * {@link InvalidObjectException} to be thrown. The high 1153 * order 24 bits are zero when an instance is serialized, 1154 * and they are ignored when an instance is deserialized. 1155 * They can thus be used by future implementations without 1156 * causing compatibility issues. 1157 * 1158 * <p>The tag value also determines the interpretation of the 1159 * transient {@code Object[] array} field. 1160 * For {@code List} and {@code Set}, the array's length is the size 1181 1182 CollSer(int t, Object... a) { 1183 tag = t; 1184 array = a; 1185 } 1186 1187 /** 1188 * Reads objects from the stream and stores them 1189 * in the transient {@code Object[] array} field. 1190 * 1191 * @serialData 1192 * A nonnegative int, indicating the count of objects, 1193 * followed by that many objects. 1194 * 1195 * @param ois the ObjectInputStream from which data is read 1196 * @throws IOException if an I/O error occurs 1197 * @throws ClassNotFoundException if a serialized class cannot be loaded 1198 * @throws InvalidObjectException if the count is negative 1199 * @since 9 1200 */ 1201 private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { 1202 ois.defaultReadObject(); 1203 int len = ois.readInt(); 1204 1205 if (len < 0) { 1206 throw new InvalidObjectException("negative length " + len); 1207 } 1208 1209 SharedSecrets.getJavaObjectInputStreamAccess().checkArray(ois, Object[].class, len); 1210 Object[] a = new Object[len]; 1211 for (int i = 0; i < len; i++) { 1212 a[i] = ois.readObject(); 1213 } 1214 1215 array = a; 1216 } 1217 1218 /** 1219 * Writes objects to the stream from 1220 * the transient {@code Object[] array} field. 1221 * 1222 * @serialData 1223 * A nonnegative int, indicating the count of objects, 1224 * followed by that many objects. 1225 * 1226 * @param oos the ObjectOutputStream to which data is written 1227 * @throws IOException if an I/O error occurs 1228 * @since 9 1229 */ 1230 private void writeObject(ObjectOutputStream oos) throws IOException { 1231 oos.defaultWriteObject(); 1232 oos.writeInt(array.length); 1233 for (int i = 0; i < array.length; i++) { 1234 oos.writeObject(array[i]); 1235 } 1236 } 1237 1238 /** 1239 * Creates and returns an immutable collection from this proxy class. 1240 * The instance returned is created as if by calling one of the 1241 * static factory methods for 1242 * <a href="List.html#unmodifiable">List</a>, 1243 * <a href="Map.html#unmodifiable">Map</a>, or 1244 * <a href="Set.html#unmodifiable">Set</a>. 1245 * This proxy class is the serial form for all immutable collection instances, 1246 * regardless of implementation type. This is necessary to ensure that the 1247 * existence of any particular implementation type is kept out of the 1248 * serialized form. 1249 * 1250 * @return a collection created from this proxy object 1251 * @throws InvalidObjectException if the tag value is illegal or if an exception 1252 * is thrown during creation of the collection 1253 * @throws ObjectStreamException if another serialization error has occurred 1254 * @since 9 1255 */ 1256 private Object readResolve() throws ObjectStreamException { 1257 try { 1258 if (array == null) { 1259 throw new InvalidObjectException("null array"); 1260 } 1261 1262 // use low order 8 bits to indicate "kind" 1263 // ignore high order 24 bits 1264 switch (tag & 0xff) { 1265 case IMM_LIST: 1266 return List.of(array); 1267 case IMM_SET: 1268 return Set.of(array); 1269 case IMM_MAP: 1270 if (array.length == 0) { 1271 return ImmutableCollections.MapN.EMPTY_MAP; 1272 } else if (array.length == 2) { 1273 return new ImmutableCollections.Map1<>(array[0], array[1]); 1274 } else { 1275 return new ImmutableCollections.MapN<>(array); | 401 @Override 402 public int size() { 403 return e1 != null ? 2 : 1; 404 } 405 406 @Override 407 public boolean isEmpty() { 408 return false; 409 } 410 411 @Override 412 public E get(int index) { 413 if (index == 0) { 414 return e0; 415 } else if (index == 1 && e1 != null) { 416 return e1; 417 } 418 throw outOfBounds(index); 419 } 420 421 @java.io.Serial 422 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 423 throw new InvalidObjectException("not serial proxy"); 424 } 425 426 @java.io.Serial 427 private Object writeReplace() { 428 if (e1 == null) { 429 return new CollSer(CollSer.IMM_LIST, e0); 430 } else { 431 return new CollSer(CollSer.IMM_LIST, e0, e1); 432 } 433 } 434 435 @Override 436 public Object[] toArray() { 437 if (e1 == null) { 438 return new Object[] { e0 }; 439 } else { 440 return new Object[] { e0, e1 }; 441 } 442 } 443 444 @Override 445 @SuppressWarnings("unchecked") 446 public <T> T[] toArray(T[] a) { 483 tmp[i] = Objects.requireNonNull(input[i]); 484 } 485 elements = tmp; 486 } 487 488 @Override 489 public boolean isEmpty() { 490 return elements.length == 0; 491 } 492 493 @Override 494 public int size() { 495 return elements.length; 496 } 497 498 @Override 499 public E get(int index) { 500 return elements[index]; 501 } 502 503 @java.io.Serial 504 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 505 throw new InvalidObjectException("not serial proxy"); 506 } 507 508 @java.io.Serial 509 private Object writeReplace() { 510 return new CollSer(CollSer.IMM_LIST, elements); 511 } 512 513 @Override 514 public Object[] toArray() { 515 return Arrays.copyOf(elements, elements.length); 516 } 517 518 @Override 519 @SuppressWarnings("unchecked") 520 public <T> T[] toArray(T[] a) { 521 int size = elements.length; 522 if (a.length < size) { 523 // Make a new array of a's runtime type, but my contents: 524 return (T[]) Arrays.copyOf(elements, size, a.getClass()); 525 } 526 System.arraycopy(elements, 0, a, 0, size); 527 if (a.length > size) { 528 a[size] = null; // null-terminate 610 @Override 611 public boolean hasNext() { 612 return idx > 0; 613 } 614 615 @Override 616 public E next() { 617 if (idx == 1) { 618 idx = 0; 619 return SALT >= 0 || e1 == null ? e0 : e1; 620 } else if (idx == 2) { 621 idx = 1; 622 return SALT >= 0 ? e1 : e0; 623 } else { 624 throw new NoSuchElementException(); 625 } 626 } 627 }; 628 } 629 630 @java.io.Serial 631 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 632 throw new InvalidObjectException("not serial proxy"); 633 } 634 635 @java.io.Serial 636 private Object writeReplace() { 637 if (e1 == null) { 638 return new CollSer(CollSer.IMM_SET, e0); 639 } else { 640 return new CollSer(CollSer.IMM_SET, e0, e1); 641 } 642 } 643 644 @Override 645 public Object[] toArray() { 646 if (e1 == null) { 647 return new Object[] { e0 }; 648 } else if (SALT >= 0) { 649 return new Object[] { e1, e0 }; 650 } else { 651 return new Object[] { e0, e1 }; 652 } 653 } 654 655 @Override 795 } 796 797 // returns index at which element is present; or if absent, 798 // (-i - 1) where i is location where element should be inserted. 799 // Callers are relying on this method to perform an implicit nullcheck 800 // of pe 801 private int probe(Object pe) { 802 int idx = Math.floorMod(pe.hashCode(), elements.length); 803 while (true) { 804 E ee = elements[idx]; 805 if (ee == null) { 806 return -idx - 1; 807 } else if (pe.equals(ee)) { 808 return idx; 809 } else if (++idx == elements.length) { 810 idx = 0; 811 } 812 } 813 } 814 815 @java.io.Serial 816 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 817 throw new InvalidObjectException("not serial proxy"); 818 } 819 820 @java.io.Serial 821 private Object writeReplace() { 822 Object[] array = new Object[size]; 823 int dest = 0; 824 for (Object o : elements) { 825 if (o != null) { 826 array[dest++] = o; 827 } 828 } 829 return new CollSer(CollSer.IMM_SET, array); 830 } 831 832 @Override 833 public Object[] toArray() { 834 Object[] array = new Object[size]; 835 Iterator<E> it = iterator(); 836 for (int i = 0; i < size; i++) { 837 array[i] = it.next(); 838 } 839 return array; 840 } 897 @Override 898 public boolean containsKey(Object o) { 899 return o.equals(k0); // implicit nullcheck of o 900 } 901 902 @Override 903 public boolean containsValue(Object o) { 904 return o.equals(v0); // implicit nullcheck of o 905 } 906 907 @Override 908 public int size() { 909 return 1; 910 } 911 912 @Override 913 public boolean isEmpty() { 914 return false; 915 } 916 917 @java.io.Serial 918 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 919 throw new InvalidObjectException("not serial proxy"); 920 } 921 922 @java.io.Serial 923 private Object writeReplace() { 924 return new CollSer(CollSer.IMM_MAP, k0, v0); 925 } 926 927 @Override 928 public int hashCode() { 929 return k0.hashCode() ^ v0.hashCode(); 930 } 931 } 932 933 /** 934 * An array-based Map implementation. There is a single array "table" that 935 * contains keys and values interleaved: table[0] is kA, table[1] is vA, 936 * table[2] is kB, table[3] is vB, etc. The table size must be even. It must 937 * also be strictly larger than the size (the number of key-value pairs contained 938 * in the map) so that at least one null key is always present. 939 * @param <K> the key type 940 * @param <V> the value type 941 */ 942 static final class MapN<K,V> extends AbstractImmutableMap<K,V> { 1103 1104 // returns index at which the probe key is present; or if absent, 1105 // (-i - 1) where i is location where element should be inserted. 1106 // Callers are relying on this method to perform an implicit nullcheck 1107 // of pk. 1108 private int probe(Object pk) { 1109 int idx = Math.floorMod(pk.hashCode(), table.length >> 1) << 1; 1110 while (true) { 1111 @SuppressWarnings("unchecked") 1112 K ek = (K)table[idx]; 1113 if (ek == null) { 1114 return -idx - 1; 1115 } else if (pk.equals(ek)) { 1116 return idx; 1117 } else if ((idx += 2) == table.length) { 1118 idx = 0; 1119 } 1120 } 1121 } 1122 1123 @java.io.Serial 1124 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 1125 throw new InvalidObjectException("not serial proxy"); 1126 } 1127 1128 @java.io.Serial 1129 private Object writeReplace() { 1130 Object[] array = new Object[2 * size]; 1131 int len = table.length; 1132 int dest = 0; 1133 for (int i = 0; i < len; i += 2) { 1134 if (table[i] != null) { 1135 array[dest++] = table[i]; 1136 array[dest++] = table[i+1]; 1137 } 1138 } 1139 return new CollSer(CollSer.IMM_MAP, array); 1140 } 1141 } 1142 } 1143 1144 // ---------- Serialization Proxy ---------- 1145 1146 /** 1147 * A unified serialization proxy class for the immutable collections. 1148 * 1149 * @serial 1150 * @since 9 1151 */ 1152 final class CollSer implements Serializable { 1153 @java.io.Serial 1154 private static final long serialVersionUID = 6309168927139932177L; 1155 1156 static final int IMM_LIST = 1; 1157 static final int IMM_SET = 2; 1158 static final int IMM_MAP = 3; 1159 1160 /** 1161 * Indicates the type of collection that is serialized. 1162 * The low order 8 bits have the value 1 for an immutable 1163 * {@code List}, 2 for an immutable {@code Set}, and 3 for 1164 * an immutable {@code Map}. Any other value causes an 1165 * {@link InvalidObjectException} to be thrown. The high 1166 * order 24 bits are zero when an instance is serialized, 1167 * and they are ignored when an instance is deserialized. 1168 * They can thus be used by future implementations without 1169 * causing compatibility issues. 1170 * 1171 * <p>The tag value also determines the interpretation of the 1172 * transient {@code Object[] array} field. 1173 * For {@code List} and {@code Set}, the array's length is the size 1194 1195 CollSer(int t, Object... a) { 1196 tag = t; 1197 array = a; 1198 } 1199 1200 /** 1201 * Reads objects from the stream and stores them 1202 * in the transient {@code Object[] array} field. 1203 * 1204 * @serialData 1205 * A nonnegative int, indicating the count of objects, 1206 * followed by that many objects. 1207 * 1208 * @param ois the ObjectInputStream from which data is read 1209 * @throws IOException if an I/O error occurs 1210 * @throws ClassNotFoundException if a serialized class cannot be loaded 1211 * @throws InvalidObjectException if the count is negative 1212 * @since 9 1213 */ 1214 @java.io.Serial 1215 private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { 1216 ois.defaultReadObject(); 1217 int len = ois.readInt(); 1218 1219 if (len < 0) { 1220 throw new InvalidObjectException("negative length " + len); 1221 } 1222 1223 SharedSecrets.getJavaObjectInputStreamAccess().checkArray(ois, Object[].class, len); 1224 Object[] a = new Object[len]; 1225 for (int i = 0; i < len; i++) { 1226 a[i] = ois.readObject(); 1227 } 1228 1229 array = a; 1230 } 1231 1232 /** 1233 * Writes objects to the stream from 1234 * the transient {@code Object[] array} field. 1235 * 1236 * @serialData 1237 * A nonnegative int, indicating the count of objects, 1238 * followed by that many objects. 1239 * 1240 * @param oos the ObjectOutputStream to which data is written 1241 * @throws IOException if an I/O error occurs 1242 * @since 9 1243 */ 1244 @java.io.Serial 1245 private void writeObject(ObjectOutputStream oos) throws IOException { 1246 oos.defaultWriteObject(); 1247 oos.writeInt(array.length); 1248 for (int i = 0; i < array.length; i++) { 1249 oos.writeObject(array[i]); 1250 } 1251 } 1252 1253 /** 1254 * Creates and returns an immutable collection from this proxy class. 1255 * The instance returned is created as if by calling one of the 1256 * static factory methods for 1257 * <a href="List.html#unmodifiable">List</a>, 1258 * <a href="Map.html#unmodifiable">Map</a>, or 1259 * <a href="Set.html#unmodifiable">Set</a>. 1260 * This proxy class is the serial form for all immutable collection instances, 1261 * regardless of implementation type. This is necessary to ensure that the 1262 * existence of any particular implementation type is kept out of the 1263 * serialized form. 1264 * 1265 * @return a collection created from this proxy object 1266 * @throws InvalidObjectException if the tag value is illegal or if an exception 1267 * is thrown during creation of the collection 1268 * @throws ObjectStreamException if another serialization error has occurred 1269 * @since 9 1270 */ 1271 @java.io.Serial 1272 private Object readResolve() throws ObjectStreamException { 1273 try { 1274 if (array == null) { 1275 throw new InvalidObjectException("null array"); 1276 } 1277 1278 // use low order 8 bits to indicate "kind" 1279 // ignore high order 24 bits 1280 switch (tag & 0xff) { 1281 case IMM_LIST: 1282 return List.of(array); 1283 case IMM_SET: 1284 return Set.of(array); 1285 case IMM_MAP: 1286 if (array.length == 0) { 1287 return ImmutableCollections.MapN.EMPTY_MAP; 1288 } else if (array.length == 2) { 1289 return new ImmutableCollections.Map1<>(array[0], array[1]); 1290 } else { 1291 return new ImmutableCollections.MapN<>(array); |