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