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