Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)
Frames | No Frames

Source for java.util.AbstractMap

 1:  /* AbstractMap.java -- Abstract implementation of most of Map
 2:  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005
 3:  Free Software Foundation, Inc.
 4: 
 5: This file is part of GNU Classpath.
 6: 
 7: GNU Classpath is free software; you can redistribute it and/or modify
 8: it under the terms of the GNU General Public License as published by
 9: the Free Software Foundation; either version 2, or (at your option)
 10: any later version.
 11: 
 12: GNU Classpath is distributed in the hope that it will be useful, but
 13: WITHOUT ANY WARRANTY; without even the implied warranty of
 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 15: General Public License for more details.
 16: 
 17: You should have received a copy of the GNU General Public License
 18: along with GNU Classpath; see the file COPYING. If not, write to the
 19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 20: 02110-1301 USA.
 21: 
 22: Linking this library statically or dynamically with other modules is
 23: making a combined work based on this library. Thus, the terms and
 24: conditions of the GNU General Public License cover the whole
 25: combination.
 26: 
 27: As a special exception, the copyright holders of this library give you
 28: permission to link this library with independent modules to produce an
 29: executable, regardless of the license terms of these independent
 30: modules, and to copy and distribute the resulting executable under
 31: terms of your choice, provided that you also meet, for each linked
 32: independent module, the terms and conditions of the license of that
 33: module. An independent module is a module which is not derived from
 34: or based on this library. If you modify this library, you may extend
 35: this exception to your version of the library, but you are not
 36: obligated to do so. If you do not wish to do so, delete this
 37: exception statement from your version. */
 38: 
 39: 
 40:  package java.util;
 41: 
 42:  import java.io.Serializable;
 43: 
 44:  /**
 45:  * An abstract implementation of Map to make it easier to create your own
 46:  * implementations. In order to create an unmodifiable Map, subclass
 47:  * AbstractMap and implement the <code>entrySet</code> (usually via an
 48:  * AbstractSet). To make it modifiable, also implement <code>put</code>,
 49:  * and have <code>entrySet().iterator()</code> support <code>remove</code>.
 50:  * <p>
 51:  *
 52:  * It is recommended that classes which extend this support at least the
 53:  * no-argument constructor, and a constructor which accepts another Map.
 54:  * Further methods in this class may be overridden if you have a more
 55:  * efficient implementation.
 56:  *
 57:  * @author Original author unknown
 58:  * @author Bryce McKinlay
 59:  * @author Eric Blake (ebb9@email.byu.edu)
 60:  * @see Map
 61:  * @see Collection
 62:  * @see HashMap
 63:  * @see LinkedHashMap
 64:  * @see TreeMap
 65:  * @see WeakHashMap
 66:  * @see IdentityHashMap
 67:  * @since 1.2
 68:  * @status updated to 1.4
 69:  */
 70:  public abstract class AbstractMap<K, V> implements Map<K, V>
 71: {
 72:  /** 
 73:  * A class containing an immutable key and value. The
 74:  * implementation of {@link Entry#setValue(V)} for this class
 75:  * simply throws an {@link UnsupportedOperationException},
 76:  * thus preventing changes being made. This is useful when
 77:  * a static thread-safe view of a map is required.
 78:  *
 79:  * @since 1.6 
 80:  */
 81:  public static class SimpleImmutableEntry<K, V>
 82:  implements Entry<K, V>, Serializable
 83:  {
 84:  /**
 85:  * Compatible with JDK 1.6
 86:  */
 87:  private static final long serialVersionUID = 7138329143949025153L;
 88: 
 89:  K key;
 90:  V value;
 91: 
 92:  public SimpleImmutableEntry(K key, V value)
 93:  {
 94:  this.key = key;
 95:  this.value = value;
 96:  }
 97: 
 98:  public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry)
 99:  {
 100:  this(entry.getKey(), entry.getValue());
 101:  }
 102: 
 103:  public K getKey()
 104:  {
 105:  return key;
 106:  }
 107: 
 108:  public V getValue()
 109:  {
 110:  return value;
 111:  }
 112: 
 113:  public V setValue(V value)
 114:  {
 115:  throw new UnsupportedOperationException("setValue not supported on immutable entry");
 116:  }
 117:  }
 118: 
 119:  /** An "enum" of iterator types. */
 120:  // Package visible for use by subclasses.
 121:  static final int KEYS = 0,
 122:  VALUES = 1,
 123:  ENTRIES = 2;
 124: 
 125:  /**
 126:  * The cache for {@link #keySet()}.
 127:  */
 128:  // Package visible for use by subclasses.
 129:  Set<K> keys;
 130: 
 131:  /**
 132:  * The cache for {@link #values()}.
 133:  */
 134:  // Package visible for use by subclasses.
 135:  Collection<V> values;
 136: 
 137:  /**
 138:  * The main constructor, for use by subclasses.
 139:  */
 140:  protected AbstractMap()
 141:  {
 142:  }
 143: 
 144:  /**
 145:  * Returns a set view of the mappings in this Map. Each element in the
 146:  * set must be an implementation of Map.Entry. The set is backed by
 147:  * the map, so that changes in one show up in the other. Modifications
 148:  * made while an iterator is in progress cause undefined behavior. If
 149:  * the set supports removal, these methods must be valid:
 150:  * <code>Iterator.remove</code>, <code>Set.remove</code>,
 151:  * <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
 152:  * Element addition is not supported via this set.
 153:  *
 154:  * @return the entry set
 155:  * @see Map.Entry
 156:  */
 157:  public abstract Set<Map.Entry<K, V>> entrySet();
 158: 
 159:  /**
 160:  * Remove all entries from this Map (optional operation). This default
 161:  * implementation calls entrySet().clear(). NOTE: If the entry set does
 162:  * not permit clearing, then this will fail, too. Subclasses often
 163:  * override this for efficiency. Your implementation of entrySet() should
 164:  * not call <code>AbstractMap.clear</code> unless you want an infinite loop.
 165:  *
 166:  * @throws UnsupportedOperationException if <code>entrySet().clear()</code>
 167:  * does not support clearing.
 168:  * @see Set#clear()
 169:  */
 170:  public void clear()
 171:  {
 172:  entrySet().clear();
 173:  }
 174: 
 175:  /**
 176:  * Create a shallow copy of this Map, no keys or values are copied. The
 177:  * default implementation simply calls <code>super.clone()</code>.
 178:  *
 179:  * @return the shallow clone
 180:  * @throws CloneNotSupportedException if a subclass is not Cloneable
 181:  * @see Cloneable
 182:  * @see Object#clone()
 183:  */
 184:  protected Object clone() throws CloneNotSupportedException
 185:  {
 186:  AbstractMap<K, V> copy = (AbstractMap<K, V>) super.clone();
 187:  // Clear out the caches; they are stale.
 188:  copy.keys = null;
 189:  copy.values = null;
 190:  return copy;
 191:  }
 192: 
 193:  /**
 194:  * Returns true if this contains a mapping for the given key. This
 195:  * implementation does a linear search, O(n), over the
 196:  * <code>entrySet()</code>, returning <code>true</code> if a match
 197:  * is found, <code>false</code> if the iteration ends. Many subclasses
 198:  * can implement this more efficiently.
 199:  *
 200:  * @param key the key to search for
 201:  * @return true if the map contains the key
 202:  * @throws NullPointerException if key is <code>null</code> but the map
 203:  * does not permit null keys
 204:  * @see #containsValue(Object)
 205:  */
 206:  public boolean containsKey(Object key)
 207:  {
 208:  Iterator<Map.Entry<K, V>> entries = entrySet().iterator();
 209:  int pos = size();
 210:  while (--pos >= 0)
 211:  if (equals(key, entries.next().getKey()))
 212:  return true;
 213:  return false;
 214:  }
 215: 
 216:  /**
 217:  * Returns true if this contains at least one mapping with the given value.
 218:  * This implementation does a linear search, O(n), over the
 219:  * <code>entrySet()</code>, returning <code>true</code> if a match
 220:  * is found, <code>false</code> if the iteration ends. A match is
 221:  * defined as a value, v, where <code>(value == null ? v == null :
 222:  * value.equals(v))</code>. Subclasses are unlikely to implement
 223:  * this more efficiently.
 224:  *
 225:  * @param value the value to search for
 226:  * @return true if the map contains the value
 227:  * @see #containsKey(Object)
 228:  */
 229:  public boolean containsValue(Object value)
 230:  {
 231:  Iterator<Map.Entry<K, V>> entries = entrySet().iterator();
 232:  int pos = size();
 233:  while (--pos >= 0)
 234:  if (equals(value, entries.next().getValue()))
 235:  return true;
 236:  return false;
 237:  }
 238: 
 239:  /**
 240:  * Compares the specified object with this map for equality. Returns
 241:  * <code>true</code> if the other object is a Map with the same mappings,
 242:  * that is,<br>
 243:  * <code>o instanceof Map && entrySet().equals(((Map) o).entrySet();</code>
 244:  *
 245:  * @param o the object to be compared
 246:  * @return true if the object equals this map
 247:  * @see Set#equals(Object)
 248:  */
 249:  public boolean equals(Object o)
 250:  {
 251:  return (o == this
 252:  || (o instanceof Map
 253:  && entrySet().equals(((Map<K, V>) o).entrySet())));
 254:  }
 255: 
 256:  /**
 257:  * Returns the value mapped by the given key. Returns <code>null</code> if
 258:  * there is no mapping. However, in Maps that accept null values, you
 259:  * must rely on <code>containsKey</code> to determine if a mapping exists.
 260:  * This iteration takes linear time, searching entrySet().iterator() of
 261:  * the key. Many implementations override this method.
 262:  *
 263:  * @param key the key to look up
 264:  * @return the value associated with the key, or null if key not in map
 265:  * @throws NullPointerException if this map does not accept null keys
 266:  * @see #containsKey(Object)
 267:  */
 268:  public V get(Object key)
 269:  {
 270:  Iterator<Map.Entry<K, V>> entries = entrySet().iterator();
 271:  int pos = size();
 272:  while (--pos >= 0)
 273:  {
 274:  Map.Entry<K, V> entry = entries.next();
 275:  if (equals(key, entry.getKey()))
 276:  return entry.getValue();
 277:  }
 278:  return null;
 279:  }
 280: 
 281:  /**
 282:  * Returns the hash code for this map. As defined in Map, this is the sum
 283:  * of all hashcodes for each Map.Entry object in entrySet, or basically
 284:  * entrySet().hashCode().
 285:  *
 286:  * @return the hash code
 287:  * @see Map.Entry#hashCode()
 288:  * @see Set#hashCode()
 289:  */
 290:  public int hashCode()
 291:  {
 292:  return entrySet().hashCode();
 293:  }
 294: 
 295:  /**
 296:  * Returns true if the map contains no mappings. This is implemented by
 297:  * <code>size() == 0</code>.
 298:  *
 299:  * @return true if the map is empty
 300:  * @see #size()
 301:  */
 302:  public boolean isEmpty()
 303:  {
 304:  return size() == 0;
 305:  }
 306: 
 307:  /**
 308:  * Returns a set view of this map's keys. The set is backed by the map,
 309:  * so changes in one show up in the other. Modifications while an iteration
 310:  * is in progress produce undefined behavior. The set supports removal
 311:  * if entrySet() does, but does not support element addition.
 312:  * <p>
 313:  *
 314:  * This implementation creates an AbstractSet, where the iterator wraps
 315:  * the entrySet iterator, size defers to the Map's size, and contains
 316:  * defers to the Map's containsKey. The set is created on first use, and
 317:  * returned on subsequent uses, although since no synchronization occurs,
 318:  * there is a slight possibility of creating two sets.
 319:  *
 320:  * @return a Set view of the keys
 321:  * @see Set#iterator()
 322:  * @see #size()
 323:  * @see #containsKey(Object)
 324:  * @see #values()
 325:  */
 326:  public Set<K> keySet()
 327:  {
 328:  if (keys == null)
 329:  keys = new AbstractSet<K>()
 330:  {
 331:  /**
 332:  * Retrieves the number of keys in the backing map.
 333:  *
 334:  * @return The number of keys.
 335:  */
 336:  public int size()
 337:  {
 338:  return AbstractMap.this.size();
 339:  }
 340: 
 341:  /**
 342:  * Returns true if the backing map contains the
 343:  * supplied key.
 344:  *
 345:  * @param key The key to search for.
 346:  * @return True if the key was found, false otherwise.
 347:  */
 348:  public boolean contains(Object key)
 349:  {
 350:  return containsKey(key);
 351:  }
 352: 
 353:  /**
 354:  * Returns an iterator which iterates over the keys
 355:  * in the backing map, using a wrapper around the
 356:  * iterator returned by <code>entrySet()</code>.
 357:  *
 358:  * @return An iterator over the keys.
 359:  */
 360:  public Iterator<K> iterator()
 361:  {
 362:  return new Iterator<K>()
 363:  {
 364:  /**
 365:  * The iterator returned by <code>entrySet()</code>.
 366:  */
 367:  private final Iterator<Map.Entry<K, V>> map_iterator
 368:  = entrySet().iterator();
 369: 
 370:  /**
 371:  * Returns true if a call to <code>next()</code> will
 372:  * return another key.
 373:  *
 374:  * @return True if the iterator has not yet reached
 375:  * the last key.
 376:  */
 377:  public boolean hasNext()
 378:  {
 379:  return map_iterator.hasNext();
 380:  }
 381: 
 382:  /**
 383:  * Returns the key from the next entry retrieved
 384:  * by the underlying <code>entrySet()</code> iterator.
 385:  *
 386:  * @return The next key.
 387:  */ 
 388:  public K next()
 389:  {
 390:  return map_iterator.next().getKey();
 391:  }
 392: 
 393:  /**
 394:  * Removes the map entry which has a key equal
 395:  * to that returned by the last call to
 396:  * <code>next()</code>.
 397:  *
 398:  * @throws UnsupportedOperationException if the
 399:  * map doesn't support removal.
 400:  */
 401:  public void remove()
 402:  {
 403:  map_iterator.remove();
 404:  }
 405:  };
 406:  }
 407:  };
 408:  return keys;
 409:  }
 410: 
 411:  /**
 412:  * Associates the given key to the given value (optional operation). If the
 413:  * map already contains the key, its value is replaced. This implementation
 414:  * simply throws an UnsupportedOperationException. Be aware that in a map
 415:  * that permits <code>null</code> values, a null return does not always
 416:  * imply that the mapping was created.
 417:  *
 418:  * @param key the key to map
 419:  * @param value the value to be mapped
 420:  * @return the previous value of the key, or null if there was no mapping
 421:  * @throws UnsupportedOperationException if the operation is not supported
 422:  * @throws ClassCastException if the key or value is of the wrong type
 423:  * @throws IllegalArgumentException if something about this key or value
 424:  * prevents it from existing in this map
 425:  * @throws NullPointerException if the map forbids null keys or values
 426:  * @see #containsKey(Object)
 427:  */
 428:  public V put(K key, V value)
 429:  {
 430:  throw new UnsupportedOperationException();
 431:  }
 432: 
 433:  /**
 434:  * Copies all entries of the given map to this one (optional operation). If
 435:  * the map already contains a key, its value is replaced. This implementation
 436:  * simply iterates over the map's entrySet(), calling <code>put</code>,
 437:  * so it is not supported if puts are not.
 438:  *
 439:  * @param m the mapping to load into this map
 440:  * @throws UnsupportedOperationException if the operation is not supported
 441:  * by this map.
 442:  * @throws ClassCastException if a key or value is of the wrong type for
 443:  * adding to this map.
 444:  * @throws IllegalArgumentException if something about a key or value
 445:  * prevents it from existing in this map.
 446:  * @throws NullPointerException if the map forbids null keys or values.
 447:  * @throws NullPointerException if <code>m</code> is null.
 448:  * @see #put(Object, Object)
 449:  */
 450:  public void putAll(Map<? extends K, ? extends V> m)
 451:  {
 452:  // FIXME: bogus circumlocution.
 453:  Iterator entries2 = m.entrySet().iterator();
 454:  Iterator<Map.Entry<? extends K, ? extends V>> entries
 455:  = (Iterator<Map.Entry<? extends K, ? extends V>>) entries2;
 456:  int pos = m.size();
 457:  while (--pos >= 0)
 458:  {
 459:  Map.Entry<? extends K, ? extends V> entry = entries.next();
 460:  put(entry.getKey(), entry.getValue());
 461:  }
 462:  }
 463: 
 464:  /**
 465:  * Removes the mapping for this key if present (optional operation). This
 466:  * implementation iterates over the entrySet searching for a matching
 467:  * key, at which point it calls the iterator's <code>remove</code> method.
 468:  * It returns the result of <code>getValue()</code> on the entry, if found,
 469:  * or null if no entry is found. Note that maps which permit null values
 470:  * may also return null if the key was removed. If the entrySet does not
 471:  * support removal, this will also fail. This is O(n), so many
 472:  * implementations override it for efficiency.
 473:  *
 474:  * @param key the key to remove
 475:  * @return the value the key mapped to, or null if not present.
 476:  * Null may also be returned if null values are allowed
 477:  * in the map and the value of this mapping is null.
 478:  * @throws UnsupportedOperationException if deletion is unsupported
 479:  * @see Iterator#remove()
 480:  */
 481:  public V remove(Object key)
 482:  {
 483:  Iterator<Map.Entry<K, V>> entries = entrySet().iterator();
 484:  int pos = size();
 485:  while (--pos >= 0)
 486:  {
 487:  Map.Entry<K, V> entry = entries.next();
 488:  if (equals(key, entry.getKey()))
 489:  {
 490:  // Must get the value before we remove it from iterator.
 491:  V r = entry.getValue();
 492:  entries.remove();
 493:  return r;
 494:  }
 495:  }
 496:  return null;
 497:  }
 498: 
 499:  /**
 500:  * Returns the number of key-value mappings in the map. If there are more
 501:  * than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE. This is
 502:  * implemented as <code>entrySet().size()</code>.
 503:  *
 504:  * @return the number of mappings
 505:  * @see Set#size()
 506:  */
 507:  public int size()
 508:  {
 509:  return entrySet().size();
 510:  }
 511: 
 512:  /**
 513:  * Returns a String representation of this map. This is a listing of the
 514:  * map entries (which are specified in Map.Entry as being
 515:  * <code>getKey() + "=" + getValue()</code>), separated by a comma and
 516:  * space (", "), and surrounded by braces ('{' and '}'). This implementation
 517:  * uses a StringBuffer and iterates over the entrySet to build the String.
 518:  * Note that this can fail with an exception if underlying keys or
 519:  * values complete abruptly in toString().
 520:  *
 521:  * @return a String representation
 522:  * @see Map.Entry#toString()
 523:  */
 524:  public String toString()
 525:  {
 526:  Iterator<Map.Entry<K, V>> entries = entrySet().iterator();
 527:  StringBuffer r = new StringBuffer("{");
 528:  for (int pos = size(); pos > 0; pos--)
 529:  {
 530:  Map.Entry<K, V> entry = entries.next();
 531:  r.append(entry.getKey());
 532:  r.append('=');
 533:  r.append(entry.getValue());
 534:  if (pos > 1)
 535:  r.append(", ");
 536:  }
 537:  r.append("}");
 538:  return r.toString();
 539:  }
 540: 
 541:  /**
 542:  * Returns a collection or bag view of this map's values. The collection
 543:  * is backed by the map, so changes in one show up in the other.
 544:  * Modifications while an iteration is in progress produce undefined
 545:  * behavior. The collection supports removal if entrySet() does, but
 546:  * does not support element addition.
 547:  * <p>
 548:  *
 549:  * This implementation creates an AbstractCollection, where the iterator
 550:  * wraps the entrySet iterator, size defers to the Map's size, and contains
 551:  * defers to the Map's containsValue. The collection is created on first
 552:  * use, and returned on subsequent uses, although since no synchronization
 553:  * occurs, there is a slight possibility of creating two collections.
 554:  *
 555:  * @return a Collection view of the values
 556:  * @see Collection#iterator()
 557:  * @see #size()
 558:  * @see #containsValue(Object)
 559:  * @see #keySet()
 560:  */
 561:  public Collection<V> values()
 562:  {
 563:  if (values == null)
 564:  values = new AbstractCollection<V>()
 565:  {
 566:  /**
 567:  * Returns the number of values stored in
 568:  * the backing map.
 569:  *
 570:  * @return The number of values.
 571:  */
 572:  public int size()
 573:  {
 574:  return AbstractMap.this.size();
 575:  }
 576: 
 577:  /**
 578:  * Returns true if the backing map contains
 579:  * the supplied value.
 580:  *
 581:  * @param value The value to search for.
 582:  * @return True if the value was found, false otherwise.
 583:  */
 584:  public boolean contains(Object value)
 585:  {
 586:  return containsValue(value);
 587:  }
 588: 
 589:  /**
 590:  * Returns an iterator which iterates over the
 591:  * values in the backing map, by using a wrapper
 592:  * around the iterator returned by <code>entrySet()</code>.
 593:  *
 594:  * @return An iterator over the values.
 595:  */
 596:  public Iterator<V> iterator()
 597:  {
 598:  return new Iterator<V>()
 599:  {
 600:  /**
 601:  * The iterator returned by <code>entrySet()</code>.
 602:  */
 603:  private final Iterator<Map.Entry<K, V>> map_iterator
 604:  = entrySet().iterator();
 605: 
 606:  /**
 607:  * Returns true if a call to <code>next()</call> will
 608:  * return another value.
 609:  *
 610:  * @return True if the iterator has not yet reached
 611:  * the last value.
 612:  */
 613:  public boolean hasNext()
 614:  {
 615:  return map_iterator.hasNext();
 616:  }
 617: 
 618:  /**
 619:  * Returns the value from the next entry retrieved
 620:  * by the underlying <code>entrySet()</code> iterator.
 621:  *
 622:  * @return The next value.
 623:  */
 624:  public V next()
 625:  {
 626:  return map_iterator.next().getValue();
 627:  }
 628: 
 629:  /**
 630:  * Removes the map entry which has a key equal
 631:  * to that returned by the last call to
 632:  * <code>next()</code>.
 633:  *
 634:  * @throws UnsupportedOperationException if the
 635:  * map doesn't support removal.
 636:  */
 637:  public void remove()
 638:  {
 639:  map_iterator.remove();
 640:  }
 641:  };
 642:  }
 643:  };
 644:  return values;
 645:  }
 646: 
 647:  /**
 648:  * Compare two objects according to Collection semantics.
 649:  *
 650:  * @param o1 the first object
 651:  * @param o2 the second object
 652:  * @return o1 == o2 || (o1 != null && o1.equals(o2))
 653:  */
 654:  // Package visible for use throughout java.util.
 655:  // It may be inlined since it is final.
 656:  static final boolean equals(Object o1, Object o2)
 657:  {
 658:  return o1 == o2 || (o1 != null && o1.equals(o2));
 659:  }
 660: 
 661:  /**
 662:  * Hash an object according to Collection semantics.
 663:  *
 664:  * @param o the object to hash
 665:  * @return o1 == null ? 0 : o1.hashCode()
 666:  */
 667:  // Package visible for use throughout java.util.
 668:  // It may be inlined since it is final.
 669:  static final int hashCode(Object o)
 670:  {
 671:  return o == null ? 0 : o.hashCode();
 672:  }
 673: 
 674:  /**
 675:  * A class which implements Map.Entry. It is shared by HashMap, TreeMap,
 676:  * Hashtable, and Collections. It is not specified by the JDK, but makes
 677:  * life much easier.
 678:  *
 679:  * @author Jon Zeppieri
 680:  * @author Eric Blake (ebb9@email.byu.edu)
 681:  * 
 682:  * @since 1.6
 683:  */
 684:  public static class SimpleEntry<K, V> implements Entry<K, V>, Serializable
 685:  {
 686: 
 687:  /**
 688:  * Compatible with JDK 1.6
 689:  */
 690:  private static final long serialVersionUID = -8499721149061103585L;
 691: 
 692:  /**
 693:  * The key. Package visible for direct manipulation.
 694:  */
 695:  K key;
 696: 
 697:  /**
 698:  * The value. Package visible for direct manipulation.
 699:  */
 700:  V value;
 701: 
 702:  /**
 703:  * Basic constructor initializes the fields.
 704:  * @param newKey the key
 705:  * @param newValue the value
 706:  */
 707:  public SimpleEntry(K newKey, V newValue)
 708:  {
 709:  key = newKey;
 710:  value = newValue;
 711:  }
 712:  
 713:  public SimpleEntry(Entry<? extends K, ? extends V> entry)
 714:  {
 715:  this(entry.getKey(), entry.getValue());
 716:  }
 717: 
 718:  /**
 719:  * Compares the specified object with this entry. Returns true only if
 720:  * the object is a mapping of identical key and value. In other words,
 721:  * this must be:<br>
 722:  * <pre>(o instanceof Map.Entry)
 723:  * && (getKey() == null ? ((HashMap) o).getKey() == null
 724:  * : getKey().equals(((HashMap) o).getKey()))
 725:  * && (getValue() == null ? ((HashMap) o).getValue() == null
 726:  * : getValue().equals(((HashMap) o).getValue()))</pre>
 727:  *
 728:  * @param o the object to compare
 729:  * @return <code>true</code> if it is equal
 730:  */
 731:  public boolean equals(Object o)
 732:  {
 733:  if (! (o instanceof Map.Entry))
 734:  return false;
 735:  // Optimize for our own entries.
 736:  if (o instanceof SimpleEntry)
 737:  {
 738:  SimpleEntry e = (SimpleEntry) o;
 739:  return (AbstractMap.equals(key, e.key)
 740:  && AbstractMap.equals(value, e.value));
 741:  }
 742:  Map.Entry e = (Map.Entry) o;
 743:  return (AbstractMap.equals(key, e.getKey())
 744:  && AbstractMap.equals(value, e.getValue()));
 745:  }
 746: 
 747:  /**
 748:  * Get the key corresponding to this entry.
 749:  *
 750:  * @return the key
 751:  */
 752:  public K getKey()
 753:  {
 754:  return key;
 755:  }
 756: 
 757:  /**
 758:  * Get the value corresponding to this entry. If you already called
 759:  * Iterator.remove(), the behavior undefined, but in this case it works.
 760:  *
 761:  * @return the value
 762:  */
 763:  public V getValue()
 764:  {
 765:  return value;
 766:  }
 767: 
 768:  /**
 769:  * Returns the hash code of the entry. This is defined as the exclusive-or
 770:  * of the hashcodes of the key and value (using 0 for null). In other
 771:  * words, this must be:<br>
 772:  * <pre>(getKey() == null ? 0 : getKey().hashCode())
 773:  * ^ (getValue() == null ? 0 : getValue().hashCode())</pre>
 774:  *
 775:  * @return the hash code
 776:  */
 777:  public int hashCode()
 778:  {
 779:  return (AbstractMap.hashCode(key) ^ AbstractMap.hashCode(value));
 780:  }
 781: 
 782:  /**
 783:  * Replaces the value with the specified object. This writes through
 784:  * to the map, unless you have already called Iterator.remove(). It
 785:  * may be overridden to restrict a null value.
 786:  *
 787:  * @param newVal the new value to store
 788:  * @return the old value
 789:  * @throws NullPointerException if the map forbids null values.
 790:  * @throws UnsupportedOperationException if the map doesn't support
 791:  * <code>put()</code>.
 792:  * @throws ClassCastException if the value is of a type unsupported
 793:  * by the map.
 794:  * @throws IllegalArgumentException if something else about this
 795:  * value prevents it being stored in the map.
 796:  */
 797:  public V setValue(V newVal)
 798:  {
 799:  V r = value;
 800:  value = newVal;
 801:  return r;
 802:  }
 803: 
 804:  /**
 805:  * This provides a string representation of the entry. It is of the form
 806:  * "key=value", where string concatenation is used on key and value.
 807:  *
 808:  * @return the string representation
 809:  */
 810:  public String toString()
 811:  {
 812:  return key + "=" + value;
 813:  }
 814:  } // class SimpleEntry
 815:  
 816:  
 817: }
Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)

AltStyle によって変換されたページ (->オリジナル) /