1 9 package javolution.util; 10 11 import j2me.io.ObjectInputStream; 12 import j2me.io.ObjectOutputStream; 13 import j2me.io.Serializable; 14 import j2me.lang.UnsupportedOperationException; 15 import j2me.util.Collection; 16 import j2me.util.Iterator; 17 import j2me.util.Map; 18 import j2me.util.Set; 19 import j2mex.realtime.MemoryArea; 20 import java.io.IOException ; 21 import java.io.PrintStream ; 22 import javolution.context.PersistentContext; 23 import javolution.context.Realtime; 24 import javolution.context.RealtimeObject; 25 import javolution.lang.Reusable; 26 import javolution.text.Text; 27 import javolution.text.TextBuilder; 28 import javolution.util.FastCollection.Record; 29 import javolution.xml.XMLBinding; 30 import javolution.xml.XMLFormat; 31 import javolution.xml.stream.XMLStreamException; 32 33 93 public class FastMapextends RealtimeObject implements Map, 94 Reusable, Serializable { 95 96 103 protected static final XMLFormatXML = new XMLFormat( 104 new FastMap().getClass()) { 105 106 public void read(InputElement xml, Object obj) 107 throws XMLStreamException { 108 final FastMap fm = (FastMap) obj; 109 fm.setShared(xml.getAttribute("shared", false)); 110 FastComparator keyComparator = (FastComparator) xml 111 .get("KeyComparator"); 112 if (keyComparator != null) { 113 fm.setKeyComparator(keyComparator); 114 } 115 FastComparator valueComparator = (FastComparator) xml 116 .get("ValueComparator"); 117 if (valueComparator != null) { 118 fm.setValueComparator(valueComparator); 119 } 120 while (xml.hasNext()) { 121 Object key = xml.get("Key"); 122 Object value = xml.get("Value"); 123 fm.put(key, value); 124 } 125 } 126 127 public void write(Object obj, OutputElement xml) 128 throws XMLStreamException { 129 final FastMap fm = (FastMap) obj; 130 if (fm.isShared()) { 131 xml.setAttribute("shared", true); 132 } 133 if (fm.getKeyComparator() != FastComparator.DEFAULT) { 134 xml.add(fm.getKeyComparator(), "KeyComparator"); 135 } 136 if (fm.getValueComparator() != FastComparator.DEFAULT) { 137 xml.add(fm.getValueComparator(), "ValueComparator"); 138 } 139 for (Entry e = fm.head(), end = fm.tail(); (e = (Entry) e.getNext()) != end;) { 140 xml.add(e.getKey(), "Key"); 141 xml.add(e.getValue(), "Value"); 142 } 143 } 144 }; 145 146 149 private static final int R0 = 5; 150 151 154 private static final int M0 = (1 << R0) - 1; 155 156 159 private static final Factory FACTORY = new Factory() { 160 161 public Object create() { 162 return new FastMap(); 163 } 164 165 public void cleanup(Object obj) { 166 ((FastMap) obj).reset(); 167 } 168 }; 169 170 174 private transient Entry[][] _entries; 175 176 180 private transient Entry_head; 181 182 186 private transient Entry_tail; 187 188 191 private transient int _size; 192 193 196 private transient Values _values; 197 198 201 private transient KeySet _keySet; 202 203 206 private transient EntrySet _entrySet; 207 208 211 private transient Map_unmodifiable; 212 213 216 private transient FastMap_oldEntries; 217 218 221 private transient FastComparator _keyComparator = FastComparator.DEFAULT; 222 223 226 private transient FastComparator _valueComparator = FastComparator.DEFAULT; 227 228 231 private transient FastComparator _keyComp 232 = FastComparator._Rehash ? FastComparator.REHASH : null; 233 234 237 private transient boolean _isShared; 238 239 242 public FastMap() { 243 this(4); 244 } 245 246 254 public FastMap(String id) { 255 this(); 256 new PersistentContext.Reference(id, this) { 257 protected void notifyChange() { 258 FastMap.this.clear(); 259 FastMap.this.putAll((FastMap) this.get()); 260 } 261 }; 262 } 263 264 271 public FastMap(int capacity) { 272 setup(capacity); 273 } 274 private void setup(int capacity) { 275 int tableLength = 1 << R0; 276 while (tableLength < capacity) { 277 tableLength <<= 1; 278 } 279 _entries = (Entry[][]) new Entry[tableLength >> R0][]; 280 for (int i = 0; i < _entries.length;) { 281 _entries[i++] = (Entry[]) new Entry[1 << R0]; 282 } 283 _head = new Entry(); 284 _tail = new Entry(); 285 _head._next = _tail; 286 _tail._previous = _head; 287 Entryprevious = _tail; 288 for (int i = 0; i++ < capacity;) { 289 EntrynewEntry = new Entry(); 290 newEntry._previous = previous; 291 previous._next = newEntry; 292 previous = newEntry; 293 } 294 } 295 296 302 public FastMap(Mapmap) { 303 this(map.size()); 304 putAll(map); 305 } 306 307 312 private FastMap(Entry[][] entries) { 313 _head = new Entry(); 314 _tail = new Entry(); 315 _head._next = _tail; 316 _tail._previous = _head; 317 _entries = entries; 318 } 319 320 327 public staticFastMapnewInstance() { 328 return (FastMap) FACTORY.object(); 329 } 330 331 336 public static void recycle(FastMap instance) { 337 FACTORY.recycle(instance); 338 } 339 340 346 public final Entryhead() { 347 return _head; 348 } 349 350 356 public final Entrytail() { 357 return _tail; 358 } 359 360 365 public final int size() { 366 return _size; 367 } 368 369 375 public final boolean isEmpty() { 376 return _head._next == _tail; 377 } 378 379 387 public final boolean containsKey(Object key) { 388 return getEntry(key) != null; 389 } 390 391 399 public final boolean containsValue(Object value) { 400 return values().contains(value); 401 } 402 403 411 public final Object get(Object key) { 412 Entryentry = getEntry(key, (_keyComp == null) ? key 413 .hashCode() : _keyComp.hashCodeOf(key)); 414 return (entry != null) ? entry._value : null; 415 } 416 417 423 public final EntrygetEntry(Object key) { 424 return getEntry(key, (_keyComp == null) ? key.hashCode() : _keyComp 425 .hashCodeOf(key)); 426 } 427 428 442 public final Object put(Object key, Object value) { 443 final int keyHash = (_keyComp == null) ? key.hashCode() : _keyComp 444 .hashCodeOf(key); 445 Entryentry = getEntry(key, keyHash); 446 if (entry != null) { 447 Object prevValue = entry._value; 448 entry._value = value; 449 return prevValue; 450 } 451 if (_isShared) return putShared(key, value, keyHash); 453 addEntry(keyHash, key, value); 454 return null; 455 } 456 457 private synchronized Object putShared(Object key, 458 Object value, int keyHash) { 459 Entryentry = getEntry(key, keyHash); if (entry == null) { addEntry(keyHash, key, value); 462 return null; 463 } 464 Object prevValue = entry._value; 465 entry._value = value; 466 return prevValue; 467 } 468 469 476 public final void putAll(Mapmap) { 477 if (map instanceof FastMap) { FastMapfm = (FastMap) map; 479 for (Entrye = fm._head, end = fm._tail; (e = e._next) != end;) { 480 put(e._key, e._value); 481 } 482 } else { 483 for (Iterator i = map.entrySet().iterator(); i.hasNext();) { 484 Map.Entrye = (Map.Entry) i 485 .next(); 486 put(e.getKey(), e.getValue()); 487 } 488 } 489 } 490 491 508 public final Object remove(Object key) { 509 Entryentry = getEntry(key); 510 if (entry == null) 511 return null; 512 if (_isShared) return removeShared(entry); 514 Object prevValue = entry._value; 515 removeEntry(entry); 516 return prevValue; 517 } 518 519 private synchronized Object removeShared(Entryentry) { 520 _size--; 521 entry.detach(); 522 return entry._value; 523 } 524 525 541 public FastMapsetShared(boolean isShared) { 542 _isShared = isShared; 543 return this; 544 } 545 546 553 public boolean isShared() { 554 return _isShared; 555 } 556 557 563 public FastMapsetKeyComparator(FastComparator keyComparator) { 564 _keyComparator = keyComparator; 565 _keyComp = (keyComparator instanceof FastComparator.Default) ? 566 (FastComparator._Rehash ? FastComparator.REHASH : null) 567 : (keyComparator instanceof FastComparator.Direct) ? null 568 : keyComparator; 569 return this; 570 } 571 572 577 public FastComparator getKeyComparator() { 578 return _keyComparator; 579 } 580 581 587 public FastMapsetValueComparator(FastComparator valueComparator) { 588 _valueComparator = valueComparator; 589 return this; 590 } 591 592 597 public FastComparator getValueComparator() { 598 return _valueComparator; 599 } 600 601 611 public final void clear() { 612 if (_isShared) { 613 clearShared(); 614 return; 615 } 616 for (Entrye = _head, end = _tail; (e = e._next) != end;) { 618 e._key = null; 619 e._value = null; 620 final Entry[][] table = e._table; 621 table[(e._keyHash >> R0) & (table.length - 1)][e._keyHash & M0] = null; 622 } 623 _tail = _head._next; 624 _size = 0; 625 626 _oldEntries = null; 628 } 629 630 private synchronized void clearShared() { 631 for (Entrye = _head, end = _tail; (e = e._next) != end;) { 632 final Entry[][] table = e._table; 633 table[(e._keyHash >> R0) & (table.length - 1)][e._keyHash & M0] = null; 634 } 635 _head._next = _tail; _tail._previous = _head; _oldEntries = null; 638 _size = 0; 639 } 640 641 651 public boolean equals(Object obj) { 652 if (obj == this) { 653 return true; 654 } else if (obj instanceof Map) { 655 Mapthat = (Map) obj; 656 return this.entrySet().equals(that.entrySet()); 657 } else { 658 return false; 659 } 660 } 661 662 667 public int hashCode() { 668 int code = 0; 669 for (Entry e = _head, end = _tail; (e = e._next) != end;) { 670 code += e.hashCode(); 671 } 672 return code; 673 } 674 675 680 public Text toText() { 681 return Text.valueOf(entrySet()); 682 } 683 684 692 public void printStatistics(PrintStream out) { 693 int maxOccupancy = 0; 694 int totalCollisions = 0; 695 int size = 0; 696 for (int i = 0; i < _entries.length; i++) { 697 for (int j = 0; j < _entries[i].length; j++) { 698 Entry entry = _entries[i][j]; 699 int occupancy = 0; 700 while (entry != null) { 701 occupancy++; 702 if (occupancy > maxOccupancy) { 703 maxOccupancy = occupancy; 704 } 705 if (occupancy > 1) { 706 totalCollisions++; 707 } 708 entry = entry._beside; 709 size++; 710 } 711 } 712 } 713 TextBuilder percentCollisions = TextBuilder.newInstance(); 714 if (size != 0) { 715 percentCollisions.append((100 * totalCollisions) / size); 716 percentCollisions.append('%'); 717 } else { 718 percentCollisions.append("N/A"); 719 } 720 synchronized (out) { 721 out.print("SIZE: " + size); 722 out 723 .print(", TABLE LENGTH: " + _entries.length 724 * _entries[0].length); 725 out.print(", AVG COLLISIONS: " + percentCollisions); 726 out.print(", MAX SLOT OCCUPANCY: " + maxOccupancy); 727 out.print(", KEY COMPARATOR: " 728 + ((_keyComp == null) ? FastComparator.DIRECT : _keyComp)); 729 out.print(", SHARED: " + _isShared); 730 out.println(); 731 if (_oldEntries != null) { 732 out.print(" + "); 733 _oldEntries.printStatistics(out); 734 } 735 } 736 } 737 738 752 public final Collectionvalues() { 753 if (_values == null) { 754 MemoryArea.getMemoryArea(this).executeInArea(new Runnable () { 755 public void run() { 756 _values = new Values(); 757 } 758 }); 759 } 760 return _values; 761 } 762 763 private final class Values extends FastCollection { 764 765 public int size() { 766 return _size; 767 } 768 769 public void clear() { 770 FastMap.this.clear(); 771 } 772 773 public Record head() { 774 return FastMap.this._head; 775 } 776 777 public Record tail() { 778 return FastMap.this._tail; 779 } 780 781 public Object valueOf(Record record) { 782 return ((Entry) record)._value; 783 } 784 785 public void delete(Record record) { 786 FastMap.this.remove(((Entry) record).getKey()); 787 } 788 789 public FastComparator getValueComparator() { 790 return _valueComparator; 791 } 792 } 793 794 808 public final SetentrySet() { 809 if (_entrySet == null) { 810 MemoryArea.getMemoryArea(this).executeInArea(new Runnable () { 811 public void run() { 812 _entrySet = new EntrySet(); 813 } 814 }); 815 } 816 return _entrySet; 817 } 818 819 private final class EntrySet extends FastCollection implements Set { 820 821 public int size() { 822 return _size; 823 } 824 825 public void clear() { 826 FastMap.this.clear(); 827 } 828 829 public boolean contains(Object obj) { if (obj instanceof Map.Entry) { 831 Map.Entry thatEntry = (Entry) obj; 832 Entry thisEntry = getEntry(thatEntry.getKey()); 833 if (thisEntry == null) return false; 834 return _valueComparator.areEqual(thisEntry.getValue(), thatEntry.getValue()); 835 } else { 836 return false; 837 } 838 } 839 840 public Text toText() { 841 Text text = Text.valueOf('['); 842 final Text equ = Text.valueOf('='); 843 final Text sep = Text.valueOf(", "); 844 for (Entry e = _head, end = _tail; (e = e._next) != end;) { 845 text = text.concat(Text.valueOf(e._key)).concat(equ).concat( 846 Text.valueOf(e._value)); 847 if (e._next != end) { 848 text = text.concat(sep); 849 } 850 } 851 return text.concat(Text.valueOf(']')); 852 } 853 854 public Record head() { 855 return _head; 856 } 857 858 public Record tail() { 859 return _tail; 860 } 861 862 public Object valueOf(Record record) { 863 return (Map.Entry) record; 864 } 865 866 public void delete(Record record) { 867 FastMap.this.remove(((Entry) record).getKey()); 868 } 869 870 public FastComparator getValueComparator() { 871 return _entryComparator; 872 } 873 private final FastComparator _entryComparator = new FastComparator() { 874 875 public boolean areEqual(Object o1, Object o2) { 876 if ((o1 instanceof Map.Entry) && (o2 instanceof Map.Entry)) { 877 Map.Entry e1 = (Map.Entry) o1; 878 Map.Entry e2 = (Map.Entry) o2; 879 return _keyComparator.areEqual(e1.getKey(), e2.getKey()) && 880 _valueComparator.areEqual(e1.getValue(), e2.getValue()); 881 } 882 return (o1 == null) && (o2 == null); 883 } 884 885 public int compare(Object o1, Object o2) { 886 return _keyComparator.compare(o1, o2); 887 } 888 889 public int hashCodeOf(Object obj) { 890 Map.Entry entry = (Map.Entry) obj; 891 return _keyComparator.hashCodeOf(entry.getKey()) + 892 _valueComparator.hashCodeOf(entry.getValue()); 893 } 894 }; 895 } 896 897 909 public final SetkeySet() { 910 if (_keySet == null) { 911 MemoryArea.getMemoryArea(this).executeInArea(new Runnable () { 912 public void run() { 913 _keySet = new KeySet(); 914 } 915 }); 916 } 917 return _keySet; 918 } 919 920 private final class KeySet extends FastCollection implements Set { 921 922 public int size() { 923 return _size; 924 } 925 926 public void clear() { 927 FastMap.this.clear(); 928 } 929 930 public boolean contains(Object obj) { return FastMap.this.containsKey(obj); 932 } 933 934 public boolean remove(Object obj) { return FastMap.this.remove(obj) != null; 936 } 937 938 public Record head() { 939 return FastMap.this._head; 940 } 941 942 public Record tail() { 943 return FastMap.this._tail; 944 } 945 946 public Object valueOf(Record record) { 947 return ((Entry) record)._key; 948 } 949 950 public void delete(Record record) { 951 FastMap.this.remove(((Entry) record).getKey()); 952 } 953 954 public FastComparator getValueComparator() { 955 return _keyComparator; 956 } 957 } 958 959 970 public final Mapunmodifiable() { 971 if (_unmodifiable == null) { 972 MemoryArea.getMemoryArea(this).executeInArea(new Runnable () { 973 public void run() { 974 _unmodifiable = new Unmodifiable(); 975 } 976 }); 977 } 978 return _unmodifiable; 979 } 980 981 988 private final EntrygetEntry(Object key, int keyHash) { 989 final Entry[][] entries = _entries; 990 Entryentry = entries[(keyHash >> R0) & (entries.length - 1)][keyHash 991 & M0]; 992 while (entry != null) { 993 if ((key == entry._key) 994 || ((entry._keyHash == keyHash) && ((_keyComp == null) ? key 995 .equals(entry._key) 996 : _keyComp.areEqual(key, entry._key)))) 997 return entry; entry = entry._beside; 999 } 1000 return (_oldEntries != null) ? _oldEntries.getEntry(key, keyHash) 1001 : null; 1002 } 1003 1004 1011 private void addEntry(int hash, Object key, Object value) { 1012 if ((_size++ >> R0) >= (_entries.length)) { increaseEntryTable(); 1015 } 1016 1017 if (_tail._next == null) { 1018 increaseCapacity(); 1019 } 1020 final Entry newTail = _tail._next; 1021 _tail._key = key; 1023 _tail._value = value; 1024 _tail._keyHash = hash; 1025 _tail._table = _entries; 1026 1027 final int index = (hash >> R0) & (_entries.length - 1); 1029 Entry[] tmp = _entries[index]; 1030 if (tmp == NULL_BLOCK) { 1031 newBlock(index); 1032 tmp = _entries[index]; 1033 } 1034 Entry beside = tmp[hash & M0]; 1035 _tail._beside = beside; 1036 tmp[hash & M0] = _tail; 1037 1038 _tail = newTail; 1040 } 1041 1042 1049 private final void removeEntry(Entry entry) { 1050 1051 _size--; 1053 1054 entry._key = null; 1056 entry._value = null; 1057 1058 entry.detach(); 1060 1061 final Entry next = _tail._next; 1063 entry._previous = _tail; 1064 entry._next = next; 1065 _tail._next = entry; 1066 if (next != null) { 1067 next._previous = entry; 1068 } 1069 } 1070 1071 private void newBlock(final int index) { 1073 MemoryArea.getMemoryArea(this).executeInArea(new Runnable () { 1074 public void run() { 1075 _entries[index] = new Entry[1 << R0]; 1076 } 1077 }); 1078 } 1079 1080 private void increaseCapacity() { 1082 MemoryArea.getMemoryArea(this).executeInArea(new Runnable () { 1083 public void run() { 1084 EntrynewEntry0 = new Entry(); 1085 _tail._next = newEntry0; 1086 newEntry0._previous = _tail; 1087 1088 EntrynewEntry1 = new Entry(); 1089 newEntry0._next = newEntry1; 1090 newEntry1._previous = newEntry0; 1091 1092 EntrynewEntry2 = new Entry(); 1093 newEntry1._next = newEntry2; 1094 newEntry2._previous = newEntry1; 1095 1096 EntrynewEntry3 = new Entry(); 1097 newEntry2._next = newEntry3; 1098 newEntry3._previous = newEntry2; 1099 } 1100 }); 1101 } 1102 1103 private void increaseEntryTable() { 1107 MemoryArea.getMemoryArea(this).executeInArea(new Runnable () { 1108 public void run() { 1109 final int newLength = _entries.length << 3; 1110 FastMaptmp; 1111 if (newLength <= (1 << 3)) { tmp = new FastMap(new Entry[1 << 3][]); } else if (newLength <= (1 << 6)) { 1114 tmp = new FastMap(new Entry[1 << 6][]); } else if (newLength <= (1 << 9)) { 1116 tmp = new FastMap(new Entry[1 << 9][]); } else if (newLength <= (1 << 12)) { 1118 tmp = new FastMap(new Entry[1 << 12][]); } else if (newLength <= (1 << 15)) { 1120 tmp = new FastMap(new Entry[1 << 15][]); } else if (newLength <= (1 << 18)) { 1122 tmp = new FastMap(new Entry[1 << 18][]); 1123 } else if (newLength <= (1 << 21)) { 1124 tmp = new FastMap(new Entry[1 << 21][]); 1125 } else if (newLength <= (1 << 24)) { 1126 tmp = new FastMap(new Entry[1 << 24][]); 1127 } else if (newLength <= (1 << 27)) { 1128 tmp = new FastMap(new Entry[1 << 27][]); 1129 } else { return; 1131 } 1132 for (int i = 0; i < tmp._entries.length;) { 1133 tmp._entries[i++] = NULL_BLOCK; 1134 } 1135 1136 final Entry[][] newEntries = tmp._entries; 1138 1139 tmp._entries = _entries; 1141 tmp._oldEntries = _oldEntries; 1142 tmp._keyComp = _keyComp; 1143 tmp._head = null; 1144 tmp._tail = null; 1145 tmp._size = -1; 1146 1147 _oldEntries = tmp; 1149 _entries = newEntries; 1151 } 1155 }); 1156 } 1157 1158 private static final Entry[] NULL_BLOCK = new Entry[1 << R0]; 1159 1160 public boolean move(ObjectSpace os) { 1162 if (super.move(os)) { 1163 for (Entry e = _head, end = _tail; (e = e._next) != end;) { 1164 if (e._key instanceof Realtime) { 1165 ((Realtime) e._key).move(os); 1166 } 1167 if (e._value instanceof Realtime) { 1168 ((Realtime) e._value).move(os); 1169 } 1170 } 1171 return true; 1172 } 1173 return false; 1174 } 1175 1176 public void reset() { 1178 setShared(false); clear(); setKeyComparator(FastComparator.DEFAULT); 1181 setValueComparator(FastComparator.DEFAULT); 1182 } 1183 1184 1192 private void readObject(ObjectInputStream stream) throws IOException , 1193 ClassNotFoundException { 1194 setKeyComparator((FastComparator) stream.readObject()); 1195 setValueComparator((FastComparator) stream.readObject()); 1196 setShared(stream.readBoolean()); 1197 final int size = stream.readInt(); 1198 setup(size); 1199 for (int i = 0; i < size; i++) { 1200 Object key = (Object ) stream.readObject(); 1201 Object value = (Object ) stream.readObject(); 1202 addEntry(_keyComparator.hashCodeOf(key), key, value); 1203 } 1204 } 1205 1206 1212 private void writeObject(ObjectOutputStream stream) throws IOException { 1213 stream.writeObject(getKeyComparator()); 1214 stream.writeObject(getValueComparator()); 1215 stream.writeBoolean(_isShared); 1216 stream.writeInt(_size); 1217 for (Entry e = _head, end = _tail; (e = e._next) != end;) { 1218 stream.writeObject(e._key); 1219 stream.writeObject(e._value); 1220 } 1221 } 1222 1223 1226 public static final class Entryimplements Map.Entry, 1227 Record { 1228 1229 1232 private Entry_next; 1233 1234 1237 private Entry_previous; 1238 1239 1242 private Object _key; 1243 1244 1247 private Object _value; 1248 1249 1252 private Entry_beside; 1253 1254 1257 private Entry[][] _table; 1258 1259 1262 private int _keyHash; 1263 1264 1267 private Entry() { 1268 } 1269 1270 1275 public final RecordgetNext() { 1276 return _next; 1277 } 1278 1279 1284 public final RecordgetPrevious() { 1285 return _previous; 1286 } 1287 1288 1293 public final Object getKey() { 1294 return _key; 1295 } 1296 1297 1302 public final Object getValue() { 1303 return _value; 1304 } 1305 1306 1312 public final Object setValue(Object value) { 1313 Object old = _value; 1314 _value = value; 1315 return old; 1316 } 1317 1318 1326 public boolean equals(Object that) { 1327 if (that instanceof Map.Entry) { 1328 Map.Entry entry = (Map.Entry) that; 1329 return _key.equals(entry.getKey()) 1330 && ((_value != null) ? _value.equals(entry.getValue()) 1331 : (entry.getValue() == null)); 1332 } else { 1333 return false; 1334 } 1335 } 1336 1337 1342 public int hashCode() { 1343 return _key.hashCode() ^ ((_value != null) ? _value.hashCode() : 0); 1344 } 1345 1346 1349 private final void detach() { 1350 _previous._next = _next; 1352 _next._previous = _previous; 1353 1354 final int index = (_keyHash >> R0) & (_table.length - 1); 1356 final Entrybeside = _beside; 1357 Entryprevious = _table[index][_keyHash & M0]; 1358 if (previous == this) { _table[index][_keyHash & M0] = beside; 1360 } else { 1361 while (previous._beside != this) { 1362 previous = previous._beside; 1363 } 1364 previous._beside = beside; 1365 } 1366 } 1367 } 1368 1369 1372 private final class Unmodifiable extends RealtimeObject implements Map, 1373 Serializable { 1374 1375 public boolean equals(Object obj) { 1376 return FastMap.this.equals(obj); 1377 } 1378 1379 public int hashCode() { 1380 return FastMap.this.hashCode(); 1381 } 1382 1383 public Text toText() { 1384 return FastMap.this.toText(); 1385 } 1386 1387 public int size() { 1388 return FastMap.this.size(); 1389 } 1390 1391 public boolean isEmpty() { 1392 return FastMap.this.isEmpty(); 1393 } 1394 1395 public boolean containsKey(Object key) { 1396 return FastMap.this.containsKey(key); 1397 } 1398 1399 public boolean containsValue(Object value) { 1400 return FastMap.this.containsValue(value); 1401 } 1402 1403 public Object get(Object key) { 1404 return FastMap.this.get(key); 1405 } 1406 1407 public Object put(Object key, Object value) { 1408 throw new UnsupportedOperationException ("Unmodifiable map"); 1409 } 1410 1411 public Object remove(Object key) { 1412 throw new UnsupportedOperationException ("Unmodifiable map"); 1413 } 1414 1415 public void putAll(Map map) { 1416 throw new UnsupportedOperationException ("Unmodifiable map"); 1417 } 1418 1419 public void clear() { 1420 throw new UnsupportedOperationException ("Unmodifiable map"); 1421 } 1422 1423 public Set keySet() { 1424 return (Set) ((KeySet)FastMap.this.keySet()).unmodifiable(); 1425 } 1426 1427 public Collection values() { 1428 return ((Values)FastMap.this.values()).unmodifiable(); 1429 } 1430 1431 public Set entrySet() { 1432 throw new UnsupportedOperationException ( 1433 "Direct view over unmodifiable map entries is not supported " 1434 + " (to prevent access to Entry.setValue(Object) method). " 1435 + "To iterate over unmodifiable map entries, applications may " 1436 + "use the keySet() and values() fast collection views " 1437 + "in conjonction."); 1438 } 1439 } 1440 1441 private static final long serialVersionUID = 1L; 1442} | Popular Tags |