001/* 002 * Copyright (C) 2007 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.google.common.collect; 018 019import static com.google.common.base.Preconditions.checkPositionIndex; 020import static com.google.common.base.Preconditions.checkState; 021import static java.util.Collections.unmodifiableList; 022import static java.util.Objects.requireNonNull; 023 024import com.google.common.annotations.GwtCompatible; 025import com.google.common.annotations.GwtIncompatible; 026import com.google.common.annotations.J2ktIncompatible; 027import com.google.errorprone.annotations.CanIgnoreReturnValue; 028import com.google.j2objc.annotations.WeakOuter; 029import java.io.IOException; 030import java.io.ObjectInputStream; 031import java.io.ObjectOutputStream; 032import java.io.Serializable; 033import java.util.AbstractSequentialList; 034import java.util.Collection; 035import java.util.ConcurrentModificationException; 036import java.util.Iterator; 037import java.util.List; 038import java.util.ListIterator; 039import java.util.Map; 040import java.util.Map.Entry; 041import java.util.NoSuchElementException; 042import java.util.Set; 043import org.jspecify.annotations.Nullable; 044 045/** 046 * An implementation of {@code ListMultimap} that supports deterministic iteration order for both 047 * keys and values. The iteration order is preserved across non-distinct key values. For example, 048 * for the following multimap definition: 049 * 050 * {@snippet : 051 * Multimap<K, V> multimap = LinkedListMultimap.create(); 052 * multimap.put(key1, foo); 053 * multimap.put(key2, bar); 054 * multimap.put(key1, baz); 055 * } 056 * 057 * ... the iteration order for {@link #keys()} is {@code [key1, key2, key1]}, and similarly for 058 * {@link #entries()}. Unlike {@link LinkedHashMultimap}, the iteration order is kept consistent 059 * between keys, entries and values. For example, calling: 060 * 061 * {@snippet : 062 * multimap.remove(key1, foo); 063 * } 064 * 065 * <p>changes the entries iteration order to {@code [key2=bar, key1=baz]} and the key iteration 066 * order to {@code [key2, key1]}. The {@link #entries()} iterator returns mutable map entries, and 067 * {@link #replaceValues} attempts to preserve iteration order as much as possible. 068 * 069 * <p>The collections returned by {@link #keySet()} and {@link #asMap} iterate through the keys in 070 * the order they were first added to the multimap. Similarly, {@link #get}, {@link #removeAll}, and 071 * {@link #replaceValues} return collections that iterate through the values in the order they were 072 * added. The collections generated by {@link #entries()}, {@link #keys()}, and {@link #values} 073 * iterate across the key-value mappings in the order they were added to the multimap. 074 * 075 * <p>The {@link #values()} and {@link #entries()} methods both return a {@code List}, instead of 076 * the {@code Collection} specified by the {@link ListMultimap} interface. 077 * 078 * <p>The methods {@link #get}, {@link #keySet()}, {@link #keys()}, {@link #values}, {@link 079 * #entries()}, and {@link #asMap} return collections that are views of the multimap. If the 080 * multimap is modified while an iteration over any of those collections is in progress, except 081 * through the iterator's methods, the results of the iteration are undefined. 082 * 083 * <p>Keys and values may be null. All optional multimap methods are supported, and all returned 084 * views are modifiable. 085 * 086 * <p>This class is not threadsafe when any concurrent operations update the multimap. Concurrent 087 * read operations will work correctly. To allow concurrent update operations, wrap your multimap 088 * with a call to {@link Multimaps#synchronizedListMultimap}. 089 * 090 * <p>See the Guava User Guide article on <a href= 091 * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">{@code Multimap}</a>. 092 * 093 * @author Mike Bostock 094 * @since 2.0 095 */ 096@GwtCompatible(serializable = true, emulated = true) 097@SuppressWarnings("WrongCommentType") // false positive 098public class LinkedListMultimap<K extends @Nullable Object, V extends @Nullable Object> 099 extends AbstractMultimap<K, V> implements ListMultimap<K, V>, Serializable { 100 /* 101 * Order is maintained using a linked list containing all key-value pairs. In 102 * addition, a series of disjoint linked lists of "siblings", each containing 103 * the values for a specific key, is used to implement {@link 104 * ValueForKeyIterator} in constant time. 105 */ 106 107 static final class Node<K extends @Nullable Object, V extends @Nullable Object> 108 extends AbstractMapEntry<K, V> { 109 @ParametricNullness final K key; 110 @ParametricNullness V value; 111 @Nullable Node<K, V> next; // the next node (with any key) 112 @Nullable Node<K, V> previous; // the previous node (with any key) 113 @Nullable Node<K, V> nextSibling; // the next node with the same key 114 @Nullable Node<K, V> previousSibling; // the previous node with the same key 115 116 Node(@ParametricNullness K key, @ParametricNullness V value) { 117 this.key = key; 118 this.value = value; 119 } 120 121 @Override 122 @ParametricNullness 123 public K getKey() { 124 return key; 125 } 126 127 @Override 128 @ParametricNullness 129 public V getValue() { 130 return value; 131 } 132 133 @Override 134 @ParametricNullness 135 public V setValue(@ParametricNullness V newValue) { 136 V result = value; 137 this.value = newValue; 138 return result; 139 } 140 } 141 142 private static class KeyList<K extends @Nullable Object, V extends @Nullable Object> { 143 Node<K, V> head; 144 Node<K, V> tail; 145 int count; 146 147 KeyList(Node<K, V> firstNode) { 148 this.head = firstNode; 149 this.tail = firstNode; 150 firstNode.previousSibling = null; 151 firstNode.nextSibling = null; 152 this.count = 1; 153 } 154 } 155 156 private transient @Nullable Node<K, V> head; // the head for all keys 157 private transient @Nullable Node<K, V> tail; // the tail for all keys 158 private transient Map<K, KeyList<K, V>> keyToKeyList; 159 private transient int size; 160 161 /* 162 * Tracks modifications to keyToKeyList so that addition or removal of keys invalidates 163 * preexisting iterators. This does *not* track simple additions and removals of values 164 * that are not the first to be added or last to be removed for their key. 165 */ 166 private transient int modCount; 167 168 /** Creates a new, empty {@code LinkedListMultimap} with the default initial capacity. */ 169 public static <K extends @Nullable Object, V extends @Nullable Object> 170 LinkedListMultimap<K, V> create() { 171 return new LinkedListMultimap<>(); 172 } 173 174 /** 175 * Constructs an empty {@code LinkedListMultimap} with enough capacity to hold the specified 176 * number of keys without rehashing. 177 * 178 * @param expectedKeys the expected number of distinct keys 179 * @throws IllegalArgumentException if {@code expectedKeys} is negative 180 */ 181 public static <K extends @Nullable Object, V extends @Nullable Object> 182 LinkedListMultimap<K, V> create(int expectedKeys) { 183 return new LinkedListMultimap<>(expectedKeys); 184 } 185 186 /** 187 * Constructs a {@code LinkedListMultimap} with the same mappings as the specified {@code 188 * Multimap}. The new multimap has the same {@link Multimap#entries()} iteration order as the 189 * input multimap. 190 * 191 * @param multimap the multimap whose contents are copied to this multimap 192 */ 193 public static <K extends @Nullable Object, V extends @Nullable Object> 194 LinkedListMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) { 195 return new LinkedListMultimap<>(multimap); 196 } 197 198 LinkedListMultimap() { 199 this(12); 200 } 201 202 private LinkedListMultimap(int expectedKeys) { 203 keyToKeyList = Platform.newHashMapWithExpectedSize(expectedKeys); 204 } 205 206 private LinkedListMultimap(Multimap<? extends K, ? extends V> multimap) { 207 this(multimap.keySet().size()); 208 putAll(multimap); 209 } 210 211 /** 212 * Adds a new node for the specified key-value pair before the specified {@code nextSibling} 213 * element, or at the end of the list if {@code nextSibling} is null. Note: if {@code nextSibling} 214 * is specified, it MUST be for a node for the same {@code key}! 215 */ 216 @CanIgnoreReturnValue 217 private Node<K, V> addNode( 218 @ParametricNullness K key, @ParametricNullness V value, @Nullable Node<K, V> nextSibling) { 219 Node<K, V> node = new Node<>(key, value); 220 if (head == null) { // empty list 221 head = tail = node; 222 keyToKeyList.put(key, new KeyList<K, V>(node)); 223 modCount++; 224 } else if (nextSibling == null) { // non-empty list, add to tail 225 // requireNonNull is safe because the list is non-empty. 226 requireNonNull(tail).next = node; 227 node.previous = tail; 228 tail = node; 229 KeyList<K, V> keyList = keyToKeyList.get(key); 230 if (keyList == null) { 231 keyToKeyList.put(key, keyList = new KeyList<>(node)); 232 modCount++; 233 } else { 234 keyList.count++; 235 Node<K, V> keyTail = keyList.tail; 236 keyTail.nextSibling = node; 237 node.previousSibling = keyTail; 238 keyList.tail = node; 239 } 240 } else { // non-empty list, insert before nextSibling 241 /* 242 * requireNonNull is safe as long as callers pass a nextSibling that (a) has the same key and 243 * (b) is present in the multimap. (And they do, except maybe in case of concurrent 244 * modification, in which case all bets are off.) 245 */ 246 KeyList<K, V> keyList = requireNonNull(keyToKeyList.get(key)); 247 keyList.count++; 248 node.previous = nextSibling.previous; 249 node.previousSibling = nextSibling.previousSibling; 250 node.next = nextSibling; 251 node.nextSibling = nextSibling; 252 if (nextSibling.previousSibling == null) { // nextSibling was key head 253 keyList.head = node; 254 } else { 255 nextSibling.previousSibling.nextSibling = node; 256 } 257 if (nextSibling.previous == null) { // nextSibling was head 258 head = node; 259 } else { 260 nextSibling.previous.next = node; 261 } 262 nextSibling.previous = node; 263 nextSibling.previousSibling = node; 264 } 265 size++; 266 return node; 267 } 268 269 /** 270 * Removes the specified node from the linked list. This method is only intended to be used from 271 * the {@code Iterator} classes. See also {@link LinkedListMultimap#removeAllNodes(Object)}. 272 */ 273 private void removeNode(Node<K, V> node) { 274 if (node.previous != null) { 275 node.previous.next = node.next; 276 } else { // node was head 277 head = node.next; 278 } 279 if (node.next != null) { 280 node.next.previous = node.previous; 281 } else { // node was tail 282 tail = node.previous; 283 } 284 if (node.previousSibling == null && node.nextSibling == null) { 285 /* 286 * requireNonNull is safe as long as we call removeNode only for nodes that are still in the 287 * Multimap. This should be the case (except in case of concurrent modification, when all bets 288 * are off). 289 */ 290 KeyList<K, V> keyList = requireNonNull(keyToKeyList.remove(node.key)); 291 keyList.count = 0; 292 modCount++; 293 } else { 294 // requireNonNull is safe (under the conditions listed in the comment in the branch above). 295 KeyList<K, V> keyList = requireNonNull(keyToKeyList.get(node.key)); 296 keyList.count--; 297 298 if (node.previousSibling == null) { 299 // requireNonNull is safe because we checked that not *both* siblings were null. 300 keyList.head = requireNonNull(node.nextSibling); 301 } else { 302 node.previousSibling.nextSibling = node.nextSibling; 303 } 304 305 if (node.nextSibling == null) { 306 // requireNonNull is safe because we checked that not *both* siblings were null. 307 keyList.tail = requireNonNull(node.previousSibling); 308 } else { 309 node.nextSibling.previousSibling = node.previousSibling; 310 } 311 } 312 size--; 313 } 314 315 /** Removes all nodes for the specified key. */ 316 private void removeAllNodes(@ParametricNullness K key) { 317 Iterators.clear(new ValueForKeyIterator(key)); 318 } 319 320 /** An {@code Iterator} over all nodes. */ 321 private class NodeIterator implements ListIterator<Entry<K, V>> { 322 int nextIndex; 323 @Nullable Node<K, V> next; 324 @Nullable Node<K, V> current; 325 @Nullable Node<K, V> previous; 326 int expectedModCount = modCount; 327 328 NodeIterator(int index) { 329 int size = size(); 330 checkPositionIndex(index, size); 331 if (index >= (size / 2)) { 332 previous = tail; 333 nextIndex = size; 334 while (index++ < size) { 335 previous(); 336 } 337 } else { 338 next = head; 339 while (index-- > 0) { 340 next(); 341 } 342 } 343 current = null; 344 } 345 346 private void checkForConcurrentModification() { 347 if (modCount != expectedModCount) { 348 throw new ConcurrentModificationException(); 349 } 350 } 351 352 @Override 353 public boolean hasNext() { 354 checkForConcurrentModification(); 355 return next != null; 356 } 357 358 @CanIgnoreReturnValue 359 @Override 360 public Node<K, V> next() { 361 checkForConcurrentModification(); 362 if (next == null) { 363 throw new NoSuchElementException(); 364 } 365 previous = current = next; 366 next = next.next; 367 nextIndex++; 368 return current; 369 } 370 371 @Override 372 public void remove() { 373 checkForConcurrentModification(); 374 checkState(current != null, "no calls to next() since the last call to remove()"); 375 if (current != next) { // after call to next() 376 previous = current.previous; 377 nextIndex--; 378 } else { // after call to previous() 379 next = current.next; 380 } 381 removeNode(current); 382 current = null; 383 expectedModCount = modCount; 384 } 385 386 @Override 387 public boolean hasPrevious() { 388 checkForConcurrentModification(); 389 return previous != null; 390 } 391 392 @CanIgnoreReturnValue 393 @Override 394 public Node<K, V> previous() { 395 checkForConcurrentModification(); 396 if (previous == null) { 397 throw new NoSuchElementException(); 398 } 399 next = current = previous; 400 previous = previous.previous; 401 nextIndex--; 402 return current; 403 } 404 405 @Override 406 public int nextIndex() { 407 return nextIndex; 408 } 409 410 @Override 411 public int previousIndex() { 412 return nextIndex - 1; 413 } 414 415 @Override 416 public void set(Entry<K, V> e) { 417 throw new UnsupportedOperationException(); 418 } 419 420 @Override 421 public void add(Entry<K, V> e) { 422 throw new UnsupportedOperationException(); 423 } 424 425 void setValue(@ParametricNullness V value) { 426 checkState(current != null); 427 current.value = value; 428 } 429 } 430 431 /** An {@code Iterator} over distinct keys in key head order. */ 432 private class DistinctKeyIterator implements Iterator<K> { 433 final Set<K> seenKeys = Sets.<K>newHashSetWithExpectedSize(keySet().size()); 434 @Nullable Node<K, V> next = head; 435 @Nullable Node<K, V> current; 436 int expectedModCount = modCount; 437 438 private void checkForConcurrentModification() { 439 if (modCount != expectedModCount) { 440 throw new ConcurrentModificationException(); 441 } 442 } 443 444 @Override 445 public boolean hasNext() { 446 checkForConcurrentModification(); 447 return next != null; 448 } 449 450 @Override 451 @ParametricNullness 452 public K next() { 453 checkForConcurrentModification(); 454 if (next == null) { 455 throw new NoSuchElementException(); 456 } 457 current = next; 458 seenKeys.add(current.key); 459 do { // skip ahead to next unseen key 460 next = next.next; 461 } while ((next != null) && !seenKeys.add(next.key)); 462 return current.key; 463 } 464 465 @Override 466 public void remove() { 467 checkForConcurrentModification(); 468 checkState(current != null, "no calls to next() since the last call to remove()"); 469 removeAllNodes(current.key); 470 current = null; 471 expectedModCount = modCount; 472 } 473 } 474 475 /** A {@code ListIterator} over values for a specified key. */ 476 private class ValueForKeyIterator implements ListIterator<V> { 477 @ParametricNullness final K key; 478 int nextIndex; 479 @Nullable Node<K, V> next; 480 @Nullable Node<K, V> current; 481 @Nullable Node<K, V> previous; 482 483 /** Constructs a new iterator over all values for the specified key. */ 484 ValueForKeyIterator(@ParametricNullness K key) { 485 this.key = key; 486 KeyList<K, V> keyList = keyToKeyList.get(key); 487 next = (keyList == null) ? null : keyList.head; 488 } 489 490 /** 491 * Constructs a new iterator over all values for the specified key starting at the specified 492 * index. This constructor is optimized so that it starts at either the head or the tail, 493 * depending on which is closer to the specified index. This allows adds to the tail to be done 494 * in constant time. 495 * 496 * @throws IndexOutOfBoundsException if index is invalid 497 */ 498 public ValueForKeyIterator(@ParametricNullness K key, int index) { 499 KeyList<K, V> keyList = keyToKeyList.get(key); 500 int size = (keyList == null) ? 0 : keyList.count; 501 checkPositionIndex(index, size); 502 if (index >= (size / 2)) { 503 previous = (keyList == null) ? null : keyList.tail; 504 nextIndex = size; 505 while (index++ < size) { 506 previous(); 507 } 508 } else { 509 next = (keyList == null) ? null : keyList.head; 510 while (index-- > 0) { 511 next(); 512 } 513 } 514 this.key = key; 515 current = null; 516 } 517 518 @Override 519 public boolean hasNext() { 520 return next != null; 521 } 522 523 @CanIgnoreReturnValue 524 @Override 525 @ParametricNullness 526 public V next() { 527 if (next == null) { 528 throw new NoSuchElementException(); 529 } 530 previous = current = next; 531 next = next.nextSibling; 532 nextIndex++; 533 return current.value; 534 } 535 536 @Override 537 public boolean hasPrevious() { 538 return previous != null; 539 } 540 541 @CanIgnoreReturnValue 542 @Override 543 @ParametricNullness 544 public V previous() { 545 if (previous == null) { 546 throw new NoSuchElementException(); 547 } 548 next = current = previous; 549 previous = previous.previousSibling; 550 nextIndex--; 551 return current.value; 552 } 553 554 @Override 555 public int nextIndex() { 556 return nextIndex; 557 } 558 559 @Override 560 public int previousIndex() { 561 return nextIndex - 1; 562 } 563 564 @Override 565 public void remove() { 566 checkState(current != null, "no calls to next() since the last call to remove()"); 567 if (current != next) { // after call to next() 568 previous = current.previousSibling; 569 nextIndex--; 570 } else { // after call to previous() 571 next = current.nextSibling; 572 } 573 removeNode(current); 574 current = null; 575 } 576 577 @Override 578 public void set(@ParametricNullness V value) { 579 checkState(current != null); 580 current.value = value; 581 } 582 583 @Override 584 public void add(@ParametricNullness V value) { 585 previous = addNode(key, value, next); 586 nextIndex++; 587 current = null; 588 } 589 } 590 591 // Query Operations 592 593 @Override 594 public int size() { 595 return size; 596 } 597 598 @Override 599 public boolean isEmpty() { 600 return head == null; 601 } 602 603 @Override 604 public boolean containsKey(@Nullable Object key) { 605 return keyToKeyList.containsKey(key); 606 } 607 608 @Override 609 public boolean containsValue(@Nullable Object value) { 610 return values().contains(value); 611 } 612 613 // Modification Operations 614 615 /** 616 * Stores a key-value pair in the multimap. 617 * 618 * @param key key to store in the multimap 619 * @param value value to store in the multimap 620 * @return {@code true} always 621 */ 622 @CanIgnoreReturnValue 623 @Override 624 public boolean put(@ParametricNullness K key, @ParametricNullness V value) { 625 addNode(key, value, null); 626 return true; 627 } 628 629 // Bulk Operations 630 631 /** 632 * {@inheritDoc} 633 * 634 * <p>If any entries for the specified {@code key} already exist in the multimap, their values are 635 * changed in-place without affecting the iteration order. 636 * 637 * <p>The returned list is immutable and implements {@link java.util.RandomAccess}. 638 */ 639 @CanIgnoreReturnValue 640 @Override 641 public List<V> replaceValues(@ParametricNullness K key, Iterable<? extends V> values) { 642 List<V> oldValues = getCopy(key); 643 ListIterator<V> keyValues = new ValueForKeyIterator(key); 644 Iterator<? extends V> newValues = values.iterator(); 645 646 // Replace existing values, if any. 647 while (keyValues.hasNext() && newValues.hasNext()) { 648 keyValues.next(); 649 keyValues.set(newValues.next()); 650 } 651 652 // Remove remaining old values, if any. 653 while (keyValues.hasNext()) { 654 keyValues.next(); 655 keyValues.remove(); 656 } 657 658 // Add remaining new values, if any. 659 while (newValues.hasNext()) { 660 keyValues.add(newValues.next()); 661 } 662 663 return oldValues; 664 } 665 666 private List<V> getCopy(@ParametricNullness K key) { 667 return unmodifiableList(Lists.newArrayList(new ValueForKeyIterator(key))); 668 } 669 670 /** 671 * {@inheritDoc} 672 * 673 * <p>The returned list is immutable and implements {@link java.util.RandomAccess}. 674 */ 675 @CanIgnoreReturnValue 676 @Override 677 public List<V> removeAll(@Nullable Object key) { 678 /* 679 * Safe because all we do is remove values for the key, not add them. (If we wanted to make sure 680 * to call getCopy and removeAllNodes only with a true K, then we could check containsKey first. 681 * But that check wouldn't eliminate the warnings.) 682 */ 683 @SuppressWarnings({"unchecked", "nullness"}) 684 K castKey = (K) key; 685 List<V> oldValues = getCopy(castKey); 686 removeAllNodes(castKey); 687 return oldValues; 688 } 689 690 @Override 691 public void clear() { 692 head = null; 693 tail = null; 694 keyToKeyList.clear(); 695 size = 0; 696 modCount++; 697 } 698 699 // Views 700 701 /** 702 * {@inheritDoc} 703 * 704 * <p>If the multimap is modified while an iteration over the list is in progress (except through 705 * the iterator's own {@code add}, {@code set} or {@code remove} operations) the results of the 706 * iteration are undefined. 707 * 708 * <p>The returned list is not serializable and does not have random access. 709 */ 710 @Override 711 public List<V> get(@ParametricNullness K key) { 712 return new AbstractSequentialList<V>() { 713 @Override 714 public int size() { 715 KeyList<K, V> keyList = keyToKeyList.get(key); 716 return (keyList == null) ? 0 : keyList.count; 717 } 718 719 @Override 720 public ListIterator<V> listIterator(int index) { 721 return new ValueForKeyIterator(key, index); 722 } 723 }; 724 } 725 726 @Override 727 Set<K> createKeySet() { 728 @WeakOuter 729 class KeySetImpl extends Sets.ImprovedAbstractSet<K> { 730 @Override 731 public int size() { 732 return keyToKeyList.size(); 733 } 734 735 @Override 736 public Iterator<K> iterator() { 737 return new DistinctKeyIterator(); 738 } 739 740 @Override 741 public boolean contains(@Nullable Object key) { // for performance 742 return containsKey(key); 743 } 744 745 @Override 746 public boolean remove(@Nullable Object o) { // for performance 747 return !LinkedListMultimap.this.removeAll(o).isEmpty(); 748 } 749 } 750 return new KeySetImpl(); 751 } 752 753 @Override 754 Multiset<K> createKeys() { 755 return new Multimaps.Keys<K, V>(this); 756 } 757 758 /** 759 * {@inheritDoc} 760 * 761 * <p>The iterator generated by the returned collection traverses the values in the order they 762 * were added to the multimap. Because the values may have duplicates and follow the insertion 763 * ordering, this method returns a {@link List}, instead of the {@link Collection} specified in 764 * the {@link ListMultimap} interface. 765 */ 766 @Override 767 public List<V> values() { 768 return (List<V>) super.values(); 769 } 770 771 @Override 772 List<V> createValues() { 773 @WeakOuter 774 class ValuesImpl extends AbstractSequentialList<V> { 775 @Override 776 public int size() { 777 return size; 778 } 779 780 @Override 781 public ListIterator<V> listIterator(int index) { 782 NodeIterator nodeItr = new NodeIterator(index); 783 return new TransformedListIterator<Entry<K, V>, V>(nodeItr) { 784 @Override 785 @ParametricNullness 786 V transform(Entry<K, V> entry) { 787 return entry.getValue(); 788 } 789 790 @Override 791 public void set(@ParametricNullness V value) { 792 nodeItr.setValue(value); 793 } 794 }; 795 } 796 } 797 return new ValuesImpl(); 798 } 799 800 /** 801 * {@inheritDoc} 802 * 803 * <p>The iterator generated by the returned collection traverses the entries in the order they 804 * were added to the multimap. Because the entries may have duplicates and follow the insertion 805 * ordering, this method returns a {@link List}, instead of the {@link Collection} specified in 806 * the {@link ListMultimap} interface. 807 * 808 * <p>An entry's {@link Entry#getKey} method always returns the same key, regardless of what 809 * happens subsequently. As long as the corresponding key-value mapping is not removed from the 810 * multimap, {@link Entry#getValue} returns the value from the multimap, which may change over 811 * time, and {@link Entry#setValue} modifies that value. Removing the mapping from the multimap 812 * does not alter the value returned by {@code getValue()}, though a subsequent {@code setValue()} 813 * call won't update the multimap but will lead to a revised value being returned by {@code 814 * getValue()}. 815 */ 816 @Override 817 public List<Entry<K, V>> entries() { 818 return (List<Entry<K, V>>) super.entries(); 819 } 820 821 @Override 822 List<Entry<K, V>> createEntries() { 823 @WeakOuter 824 class EntriesImpl extends AbstractSequentialList<Entry<K, V>> { 825 @Override 826 public int size() { 827 return size; 828 } 829 830 @Override 831 public ListIterator<Entry<K, V>> listIterator(int index) { 832 return new NodeIterator(index); 833 } 834 } 835 return new EntriesImpl(); 836 } 837 838 @Override 839 Iterator<Entry<K, V>> entryIterator() { 840 throw new AssertionError("should never be called"); 841 } 842 843 @Override 844 Map<K, Collection<V>> createAsMap() { 845 return new Multimaps.AsMap<>(this); 846 } 847 848 /** 849 * @serialData the number of distinct keys, and then for each distinct key: the first key, the 850 * number of values for that key, and the key's values, followed by successive keys and values 851 * from the entries() ordering 852 */ 853 @GwtIncompatible // java.io.ObjectOutputStream 854 @J2ktIncompatible 855 private void writeObject(ObjectOutputStream stream) throws IOException { 856 stream.defaultWriteObject(); 857 stream.writeInt(size()); 858 for (Entry<K, V> entry : entries()) { 859 stream.writeObject(entry.getKey()); 860 stream.writeObject(entry.getValue()); 861 } 862 } 863 864 @GwtIncompatible // java.io.ObjectInputStream 865 @J2ktIncompatible 866 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 867 stream.defaultReadObject(); 868 keyToKeyList = CompactLinkedHashMap.create(); 869 int size = stream.readInt(); 870 for (int i = 0; i < size; i++) { 871 @SuppressWarnings("unchecked") // reading data stored by writeObject 872 K key = (K) stream.readObject(); 873 @SuppressWarnings("unchecked") // reading data stored by writeObject 874 V value = (V) stream.readObject(); 875 put(key, value); 876 } 877 } 878 879 @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0; 880}