• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 import static com.google.common.base.Predicates.alwaysTrue;
21 import static com.google.common.base.Predicates.equalTo;
22 import static com.google.common.base.Predicates.in;
23 import static com.google.common.base.Predicates.not;
24 import static com.google.common.collect.Maps.safeContainsKey;
25 import static com.google.common.collect.Maps.safeGet;
26 import static com.google.common.collect.NullnessCasts.uncheckedCastNullableTToT;
27 import static java.util.Objects.requireNonNull;
28 
29 import com.google.common.annotations.GwtCompatible;
30 import com.google.common.base.Function;
31 import com.google.common.base.Predicate;
32 import com.google.common.base.Supplier;
33 import com.google.common.collect.Maps.IteratorBasedAbstractMap;
34 import com.google.common.collect.Maps.ViewCachingAbstractMap;
35 import com.google.common.collect.Sets.ImprovedAbstractSet;
36 import com.google.errorprone.annotations.CanIgnoreReturnValue;
37 import com.google.errorprone.annotations.concurrent.LazyInit;
38 import com.google.j2objc.annotations.WeakOuter;
39 import java.io.Serializable;
40 import java.util.Collection;
41 import java.util.Iterator;
42 import java.util.LinkedHashMap;
43 import java.util.Map;
44 import java.util.Map.Entry;
45 import java.util.Set;
46 import java.util.Spliterator;
47 import java.util.Spliterators;
48 import javax.annotation.CheckForNull;
49 
50 /**
51  * {@link Table} implementation backed by a map that associates row keys with column key / value
52  * secondary maps. This class provides rapid access to records by the row key alone or by both keys,
53  * but not by just the column key.
54  *
55  * <p>The views returned by {@link #column}, {@link #columnKeySet()}, and {@link #columnMap()} have
56  * iterators that don't support {@code remove()}. Otherwise, all optional operations are supported.
57  * Null row keys, columns keys, and values are not supported.
58  *
59  * <p>Lookups by row key are often faster than lookups by column key, because the data is stored in
60  * a {@code Map<R, Map<C, V>>}. A method call like {@code column(columnKey).get(rowKey)} still runs
61  * quickly, since the row key is provided. However, {@code column(columnKey).size()} takes longer,
62  * since an iteration across all row keys occurs.
63  *
64  * <p>Note that this implementation is not synchronized. If multiple threads access this table
65  * concurrently and one of the threads modifies the table, it must be synchronized externally.
66  *
67  * @author Jared Levy
68  */
69 @GwtCompatible
70 @ElementTypesAreNonnullByDefault
71 class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializable {
72   @GwtTransient final Map<R, Map<C, V>> backingMap;
73   @GwtTransient final Supplier<? extends Map<C, V>> factory;
74 
StandardTable(Map<R, Map<C, V>> backingMap, Supplier<? extends Map<C, V>> factory)75   StandardTable(Map<R, Map<C, V>> backingMap, Supplier<? extends Map<C, V>> factory) {
76     this.backingMap = backingMap;
77     this.factory = factory;
78   }
79 
80   // Accessors
81 
82   @Override
contains(@heckForNull Object rowKey, @CheckForNull Object columnKey)83   public boolean contains(@CheckForNull Object rowKey, @CheckForNull Object columnKey) {
84     return rowKey != null && columnKey != null && super.contains(rowKey, columnKey);
85   }
86 
87   @Override
containsColumn(@heckForNull Object columnKey)88   public boolean containsColumn(@CheckForNull Object columnKey) {
89     if (columnKey == null) {
90       return false;
91     }
92     for (Map<C, V> map : backingMap.values()) {
93       if (safeContainsKey(map, columnKey)) {
94         return true;
95       }
96     }
97     return false;
98   }
99 
100   @Override
containsRow(@heckForNull Object rowKey)101   public boolean containsRow(@CheckForNull Object rowKey) {
102     return rowKey != null && safeContainsKey(backingMap, rowKey);
103   }
104 
105   @Override
containsValue(@heckForNull Object value)106   public boolean containsValue(@CheckForNull Object value) {
107     return value != null && super.containsValue(value);
108   }
109 
110   @Override
111   @CheckForNull
get(@heckForNull Object rowKey, @CheckForNull Object columnKey)112   public V get(@CheckForNull Object rowKey, @CheckForNull Object columnKey) {
113     return (rowKey == null || columnKey == null) ? null : super.get(rowKey, columnKey);
114   }
115 
116   @Override
isEmpty()117   public boolean isEmpty() {
118     return backingMap.isEmpty();
119   }
120 
121   @Override
size()122   public int size() {
123     int size = 0;
124     for (Map<C, V> map : backingMap.values()) {
125       size += map.size();
126     }
127     return size;
128   }
129 
130   // Mutators
131 
132   @Override
clear()133   public void clear() {
134     backingMap.clear();
135   }
136 
getOrCreate(R rowKey)137   private Map<C, V> getOrCreate(R rowKey) {
138     Map<C, V> map = backingMap.get(rowKey);
139     if (map == null) {
140       map = factory.get();
141       backingMap.put(rowKey, map);
142     }
143     return map;
144   }
145 
146   @CanIgnoreReturnValue
147   @Override
148   @CheckForNull
put(R rowKey, C columnKey, V value)149   public V put(R rowKey, C columnKey, V value) {
150     checkNotNull(rowKey);
151     checkNotNull(columnKey);
152     checkNotNull(value);
153     return getOrCreate(rowKey).put(columnKey, value);
154   }
155 
156   @CanIgnoreReturnValue
157   @Override
158   @CheckForNull
remove(@heckForNull Object rowKey, @CheckForNull Object columnKey)159   public V remove(@CheckForNull Object rowKey, @CheckForNull Object columnKey) {
160     if ((rowKey == null) || (columnKey == null)) {
161       return null;
162     }
163     Map<C, V> map = safeGet(backingMap, rowKey);
164     if (map == null) {
165       return null;
166     }
167     V value = map.remove(columnKey);
168     if (map.isEmpty()) {
169       backingMap.remove(rowKey);
170     }
171     return value;
172   }
173 
174   @CanIgnoreReturnValue
removeColumn(@heckForNull Object column)175   private Map<R, V> removeColumn(@CheckForNull Object column) {
176     Map<R, V> output = new LinkedHashMap<>();
177     Iterator<Entry<R, Map<C, V>>> iterator = backingMap.entrySet().iterator();
178     while (iterator.hasNext()) {
179       Entry<R, Map<C, V>> entry = iterator.next();
180       V value = entry.getValue().remove(column);
181       if (value != null) {
182         output.put(entry.getKey(), value);
183         if (entry.getValue().isEmpty()) {
184           iterator.remove();
185         }
186       }
187     }
188     return output;
189   }
190 
containsMapping( @heckForNull Object rowKey, @CheckForNull Object columnKey, @CheckForNull Object value)191   private boolean containsMapping(
192       @CheckForNull Object rowKey, @CheckForNull Object columnKey, @CheckForNull Object value) {
193     return value != null && value.equals(get(rowKey, columnKey));
194   }
195 
196   /** Remove a row key / column key / value mapping, if present. */
removeMapping( @heckForNull Object rowKey, @CheckForNull Object columnKey, @CheckForNull Object value)197   private boolean removeMapping(
198       @CheckForNull Object rowKey, @CheckForNull Object columnKey, @CheckForNull Object value) {
199     if (containsMapping(rowKey, columnKey, value)) {
200       remove(rowKey, columnKey);
201       return true;
202     }
203     return false;
204   }
205 
206   // Views
207 
208   /**
209    * Abstract set whose {@code isEmpty()} returns whether the table is empty and whose {@code
210    * clear()} clears all table mappings.
211    */
212   @WeakOuter
213   private abstract class TableSet<T> extends ImprovedAbstractSet<T> {
214     @Override
isEmpty()215     public boolean isEmpty() {
216       return backingMap.isEmpty();
217     }
218 
219     @Override
clear()220     public void clear() {
221       backingMap.clear();
222     }
223   }
224 
225   /**
226    * {@inheritDoc}
227    *
228    * <p>The set's iterator traverses the mappings for the first row, the mappings for the second
229    * row, and so on.
230    *
231    * <p>Each cell is an immutable snapshot of a row key / column key / value mapping, taken at the
232    * time the cell is returned by a method call to the set or its iterator.
233    */
234   @Override
cellSet()235   public Set<Cell<R, C, V>> cellSet() {
236     return super.cellSet();
237   }
238 
239   @Override
cellIterator()240   Iterator<Cell<R, C, V>> cellIterator() {
241     return new CellIterator();
242   }
243 
244   private class CellIterator implements Iterator<Cell<R, C, V>> {
245     final Iterator<Entry<R, Map<C, V>>> rowIterator = backingMap.entrySet().iterator();
246     @CheckForNull Entry<R, Map<C, V>> rowEntry;
247     Iterator<Entry<C, V>> columnIterator = Iterators.emptyModifiableIterator();
248 
249     @Override
hasNext()250     public boolean hasNext() {
251       return rowIterator.hasNext() || columnIterator.hasNext();
252     }
253 
254     @Override
next()255     public Cell<R, C, V> next() {
256       if (!columnIterator.hasNext()) {
257         rowEntry = rowIterator.next();
258         columnIterator = rowEntry.getValue().entrySet().iterator();
259       }
260       /*
261        * requireNonNull is safe because:
262        *
263        * - columnIterator started off pointing to an empty iterator, so we must have entered the
264        *   `if` body above at least once. Thus, if we got this far, that `if` body initialized
265        *   rowEntry at least once.
266        *
267        * - The only case in which rowEntry is cleared (during remove() below) happens only if the
268        *   caller removed every element from columnIterator. During that process, we would have had
269        *   to iterate it to exhaustion. Then we can apply the logic above about an empty
270        *   columnIterator. (This assumes no concurrent modification, but behavior under concurrent
271        *   modification is undefined, anyway.)
272        */
273       requireNonNull(rowEntry);
274       Entry<C, V> columnEntry = columnIterator.next();
275       return Tables.immutableCell(rowEntry.getKey(), columnEntry.getKey(), columnEntry.getValue());
276     }
277 
278     @Override
remove()279     public void remove() {
280       columnIterator.remove();
281       /*
282        * requireNonNull is safe because:
283        *
284        * - columnIterator.remove() succeeded, so it must have returned a value, so it must have been
285        * initialized by next() -- which initializes rowEntry, too.
286        *
287        * - rowEntry isn't cleared except below. If it was cleared below, then either
288        *   columnIterator.remove() would have failed above (if the user hasn't called next() since
289        *   then) or rowEntry would have been initialized by next() (as discussed above).
290        */
291       if (requireNonNull(rowEntry).getValue().isEmpty()) {
292         rowIterator.remove();
293         rowEntry = null;
294       }
295     }
296   }
297 
298   @Override
cellSpliterator()299   Spliterator<Cell<R, C, V>> cellSpliterator() {
300     return CollectSpliterators.flatMap(
301         backingMap.entrySet().spliterator(),
302         (Entry<R, Map<C, V>> rowEntry) ->
303             CollectSpliterators.map(
304                 rowEntry.getValue().entrySet().spliterator(),
305                 (Entry<C, V> columnEntry) ->
306                     Tables.immutableCell(
307                         rowEntry.getKey(), columnEntry.getKey(), columnEntry.getValue())),
308         Spliterator.DISTINCT | Spliterator.SIZED,
309         size());
310   }
311 
312   @Override
row(R rowKey)313   public Map<C, V> row(R rowKey) {
314     return new Row(rowKey);
315   }
316 
317   class Row extends IteratorBasedAbstractMap<C, V> {
318     final R rowKey;
319 
Row(R rowKey)320     Row(R rowKey) {
321       this.rowKey = checkNotNull(rowKey);
322     }
323 
324     @CheckForNull Map<C, V> backingRowMap;
325 
updateBackingRowMapField()326     final void updateBackingRowMapField() {
327       if (backingRowMap == null || (backingRowMap.isEmpty() && backingMap.containsKey(rowKey))) {
328         backingRowMap = computeBackingRowMap();
329       }
330     }
331 
332     @CheckForNull
computeBackingRowMap()333     Map<C, V> computeBackingRowMap() {
334       return backingMap.get(rowKey);
335     }
336 
337     // Call this every time we perform a removal.
maintainEmptyInvariant()338     void maintainEmptyInvariant() {
339       updateBackingRowMapField();
340       if (backingRowMap != null && backingRowMap.isEmpty()) {
341         backingMap.remove(rowKey);
342         backingRowMap = null;
343       }
344     }
345 
346     @Override
containsKey(@heckForNull Object key)347     public boolean containsKey(@CheckForNull Object key) {
348       updateBackingRowMapField();
349       return (key != null && backingRowMap != null) && Maps.safeContainsKey(backingRowMap, key);
350     }
351 
352     @Override
353     @CheckForNull
get(@heckForNull Object key)354     public V get(@CheckForNull Object key) {
355       updateBackingRowMapField();
356       return (key != null && backingRowMap != null) ? Maps.safeGet(backingRowMap, key) : null;
357     }
358 
359     @Override
360     @CheckForNull
put(C key, V value)361     public V put(C key, V value) {
362       checkNotNull(key);
363       checkNotNull(value);
364       if (backingRowMap != null && !backingRowMap.isEmpty()) {
365         return backingRowMap.put(key, value);
366       }
367       return StandardTable.this.put(rowKey, key, value);
368     }
369 
370     @Override
371     @CheckForNull
remove(@heckForNull Object key)372     public V remove(@CheckForNull Object key) {
373       updateBackingRowMapField();
374       if (backingRowMap == null) {
375         return null;
376       }
377       V result = Maps.safeRemove(backingRowMap, key);
378       maintainEmptyInvariant();
379       return result;
380     }
381 
382     @Override
clear()383     public void clear() {
384       updateBackingRowMapField();
385       if (backingRowMap != null) {
386         backingRowMap.clear();
387       }
388       maintainEmptyInvariant();
389     }
390 
391     @Override
size()392     public int size() {
393       updateBackingRowMapField();
394       return (backingRowMap == null) ? 0 : backingRowMap.size();
395     }
396 
397     @Override
entryIterator()398     Iterator<Entry<C, V>> entryIterator() {
399       updateBackingRowMapField();
400       if (backingRowMap == null) {
401         return Iterators.emptyModifiableIterator();
402       }
403       final Iterator<Entry<C, V>> iterator = backingRowMap.entrySet().iterator();
404       return new Iterator<Entry<C, V>>() {
405         @Override
406         public boolean hasNext() {
407           return iterator.hasNext();
408         }
409 
410         @Override
411         public Entry<C, V> next() {
412           return wrapEntry(iterator.next());
413         }
414 
415         @Override
416         public void remove() {
417           iterator.remove();
418           maintainEmptyInvariant();
419         }
420       };
421     }
422 
423     @Override
entrySpliterator()424     Spliterator<Entry<C, V>> entrySpliterator() {
425       updateBackingRowMapField();
426       if (backingRowMap == null) {
427         return Spliterators.emptySpliterator();
428       }
429       return CollectSpliterators.map(backingRowMap.entrySet().spliterator(), this::wrapEntry);
430     }
431 
wrapEntry(final Entry<C, V> entry)432     Entry<C, V> wrapEntry(final Entry<C, V> entry) {
433       return new ForwardingMapEntry<C, V>() {
434         @Override
435         protected Entry<C, V> delegate() {
436           return entry;
437         }
438 
439         @Override
440         public V setValue(V value) {
441           return super.setValue(checkNotNull(value));
442         }
443 
444         @Override
445         public boolean equals(@CheckForNull Object object) {
446           // TODO(lowasser): identify why this affects GWT tests
447           return standardEquals(object);
448         }
449       };
450     }
451   }
452 
453   /**
454    * {@inheritDoc}
455    *
456    * <p>The returned map's views have iterators that don't support {@code remove()}.
457    */
458   @Override
459   public Map<R, V> column(C columnKey) {
460     return new Column(columnKey);
461   }
462 
463   private class Column extends ViewCachingAbstractMap<R, V> {
464     final C columnKey;
465 
466     Column(C columnKey) {
467       this.columnKey = checkNotNull(columnKey);
468     }
469 
470     @Override
471     @CheckForNull
472     public V put(R key, V value) {
473       return StandardTable.this.put(key, columnKey, value);
474     }
475 
476     @Override
477     @CheckForNull
478     public V get(@CheckForNull Object key) {
479       return StandardTable.this.get(key, columnKey);
480     }
481 
482     @Override
483     public boolean containsKey(@CheckForNull Object key) {
484       return StandardTable.this.contains(key, columnKey);
485     }
486 
487     @Override
488     @CheckForNull
489     public V remove(@CheckForNull Object key) {
490       return StandardTable.this.remove(key, columnKey);
491     }
492 
493     /** Removes all {@code Column} mappings whose row key and value satisfy the given predicate. */
494     @CanIgnoreReturnValue
495     boolean removeFromColumnIf(Predicate<? super Entry<R, V>> predicate) {
496       boolean changed = false;
497       Iterator<Entry<R, Map<C, V>>> iterator = backingMap.entrySet().iterator();
498       while (iterator.hasNext()) {
499         Entry<R, Map<C, V>> entry = iterator.next();
500         Map<C, V> map = entry.getValue();
501         V value = map.get(columnKey);
502         if (value != null && predicate.apply(Maps.immutableEntry(entry.getKey(), value))) {
503           map.remove(columnKey);
504           changed = true;
505           if (map.isEmpty()) {
506             iterator.remove();
507           }
508         }
509       }
510       return changed;
511     }
512 
513     @Override
514     Set<Entry<R, V>> createEntrySet() {
515       return new EntrySet();
516     }
517 
518     @WeakOuter
519     private class EntrySet extends ImprovedAbstractSet<Entry<R, V>> {
520       @Override
521       public Iterator<Entry<R, V>> iterator() {
522         return new EntrySetIterator();
523       }
524 
525       @Override
526       public int size() {
527         int size = 0;
528         for (Map<C, V> map : backingMap.values()) {
529           if (map.containsKey(columnKey)) {
530             size++;
531           }
532         }
533         return size;
534       }
535 
536       @Override
537       public boolean isEmpty() {
538         return !containsColumn(columnKey);
539       }
540 
541       @Override
542       public void clear() {
543         removeFromColumnIf(alwaysTrue());
544       }
545 
546       @Override
547       public boolean contains(@CheckForNull Object o) {
548         if (o instanceof Entry) {
549           Entry<?, ?> entry = (Entry<?, ?>) o;
550           return containsMapping(entry.getKey(), columnKey, entry.getValue());
551         }
552         return false;
553       }
554 
555       @Override
556       public boolean remove(@CheckForNull Object obj) {
557         if (obj instanceof Entry) {
558           Entry<?, ?> entry = (Entry<?, ?>) obj;
559           return removeMapping(entry.getKey(), columnKey, entry.getValue());
560         }
561         return false;
562       }
563 
564       @Override
565       public boolean retainAll(Collection<?> c) {
566         return removeFromColumnIf(not(in(c)));
567       }
568     }
569 
570     private class EntrySetIterator extends AbstractIterator<Entry<R, V>> {
571       final Iterator<Entry<R, Map<C, V>>> iterator = backingMap.entrySet().iterator();
572 
573       @Override
574       @CheckForNull
575       protected Entry<R, V> computeNext() {
576         while (iterator.hasNext()) {
577           final Entry<R, Map<C, V>> entry = iterator.next();
578           if (entry.getValue().containsKey(columnKey)) {
579             @WeakOuter
580             class EntryImpl extends AbstractMapEntry<R, V> {
581               @Override
582               public R getKey() {
583                 return entry.getKey();
584               }
585 
586               @Override
587               public V getValue() {
588                 return entry.getValue().get(columnKey);
589               }
590 
591               @Override
592               public V setValue(V value) {
593                 /*
594                  * The cast is safe because of the containsKey check above. (Well, it's possible for
595                  * the map to change between that call and this one. But if that happens, the
596                  * behavior is undefined because of the concurrent mutation.)
597                  *
598                  * (Our prototype checker happens to be "smart" enough to understand this for the
599                  * *get* call in getValue but not for the *put* call here.)
600                  *
601                  * (Arguably we should use requireNonNull rather than uncheckedCastNullableTToT: We
602                  * know that V is a non-null type because that's the only kind of value type that
603                  * StandardTable supports. Thus, requireNonNull is safe as long as the cell is still
604                  * present. (And if it's not present, behavior is undefined.) However, that's a
605                  * behavior change relative to the old code, so it didn't seem worth risking.)
606                  */
607                 return uncheckedCastNullableTToT(
608                     entry.getValue().put(columnKey, checkNotNull(value)));
609               }
610             }
611             return new EntryImpl();
612           }
613         }
614         return endOfData();
615       }
616     }
617 
618     @Override
619     Set<R> createKeySet() {
620       return new KeySet();
621     }
622 
623     @WeakOuter
624     private class KeySet extends Maps.KeySet<R, V> {
625       KeySet() {
626         super(Column.this);
627       }
628 
629       @Override
630       public boolean contains(@CheckForNull Object obj) {
631         return StandardTable.this.contains(obj, columnKey);
632       }
633 
634       @Override
635       public boolean remove(@CheckForNull Object obj) {
636         return StandardTable.this.remove(obj, columnKey) != null;
637       }
638 
639       @Override
640       public boolean retainAll(final Collection<?> c) {
641         return removeFromColumnIf(Maps.<R>keyPredicateOnEntries(not(in(c))));
642       }
643     }
644 
645     @Override
646     Collection<V> createValues() {
647       return new Values();
648     }
649 
650     @WeakOuter
651     private class Values extends Maps.Values<R, V> {
652       Values() {
653         super(Column.this);
654       }
655 
656       @Override
657       public boolean remove(@CheckForNull Object obj) {
658         return obj != null && removeFromColumnIf(Maps.<V>valuePredicateOnEntries(equalTo(obj)));
659       }
660 
661       @Override
662       public boolean removeAll(final Collection<?> c) {
663         return removeFromColumnIf(Maps.<V>valuePredicateOnEntries(in(c)));
664       }
665 
666       @Override
667       public boolean retainAll(final Collection<?> c) {
668         return removeFromColumnIf(Maps.<V>valuePredicateOnEntries(not(in(c))));
669       }
670     }
671   }
672 
673   @Override
674   public Set<R> rowKeySet() {
675     return rowMap().keySet();
676   }
677 
678   @LazyInit @CheckForNull private transient Set<C> columnKeySet;
679 
680   /**
681    * {@inheritDoc}
682    *
683    * <p>The returned set has an iterator that does not support {@code remove()}.
684    *
685    * <p>The set's iterator traverses the columns of the first row, the columns of the second row,
686    * etc., skipping any columns that have appeared previously.
687    */
688   @Override
689   public Set<C> columnKeySet() {
690     Set<C> result = columnKeySet;
691     return (result == null) ? columnKeySet = new ColumnKeySet() : result;
692   }
693 
694   @WeakOuter
695   private class ColumnKeySet extends TableSet<C> {
696     @Override
697     public Iterator<C> iterator() {
698       return createColumnKeyIterator();
699     }
700 
701     @Override
702     public int size() {
703       return Iterators.size(iterator());
704     }
705 
706     @Override
707     public boolean remove(@CheckForNull Object obj) {
708       if (obj == null) {
709         return false;
710       }
711       boolean changed = false;
712       Iterator<Map<C, V>> iterator = backingMap.values().iterator();
713       while (iterator.hasNext()) {
714         Map<C, V> map = iterator.next();
715         if (map.keySet().remove(obj)) {
716           changed = true;
717           if (map.isEmpty()) {
718             iterator.remove();
719           }
720         }
721       }
722       return changed;
723     }
724 
725     @Override
726     public boolean removeAll(Collection<?> c) {
727       checkNotNull(c);
728       boolean changed = false;
729       Iterator<Map<C, V>> iterator = backingMap.values().iterator();
730       while (iterator.hasNext()) {
731         Map<C, V> map = iterator.next();
732         // map.keySet().removeAll(c) can throw a NPE when map is a TreeMap with
733         // natural ordering and c contains a null.
734         if (Iterators.removeAll(map.keySet().iterator(), c)) {
735           changed = true;
736           if (map.isEmpty()) {
737             iterator.remove();
738           }
739         }
740       }
741       return changed;
742     }
743 
744     @Override
745     public boolean retainAll(Collection<?> c) {
746       checkNotNull(c);
747       boolean changed = false;
748       Iterator<Map<C, V>> iterator = backingMap.values().iterator();
749       while (iterator.hasNext()) {
750         Map<C, V> map = iterator.next();
751         if (map.keySet().retainAll(c)) {
752           changed = true;
753           if (map.isEmpty()) {
754             iterator.remove();
755           }
756         }
757       }
758       return changed;
759     }
760 
761     @Override
762     public boolean contains(@CheckForNull Object obj) {
763       return containsColumn(obj);
764     }
765   }
766 
767   /** Creates an iterator that returns each column value with duplicates omitted. */
768   Iterator<C> createColumnKeyIterator() {
769     return new ColumnKeyIterator();
770   }
771 
772   private class ColumnKeyIterator extends AbstractIterator<C> {
773     // Use the same map type to support TreeMaps with comparators that aren't
774     // consistent with equals().
775     final Map<C, V> seen = factory.get();
776     final Iterator<Map<C, V>> mapIterator = backingMap.values().iterator();
777     Iterator<Entry<C, V>> entryIterator = Iterators.emptyIterator();
778 
779     @Override
780     @CheckForNull
781     protected C computeNext() {
782       while (true) {
783         if (entryIterator.hasNext()) {
784           Entry<C, V> entry = entryIterator.next();
785           if (!seen.containsKey(entry.getKey())) {
786             seen.put(entry.getKey(), entry.getValue());
787             return entry.getKey();
788           }
789         } else if (mapIterator.hasNext()) {
790           entryIterator = mapIterator.next().entrySet().iterator();
791         } else {
792           return endOfData();
793         }
794       }
795     }
796   }
797 
798   /**
799    * {@inheritDoc}
800    *
801    * <p>The collection's iterator traverses the values for the first row, the values for the second
802    * row, and so on.
803    */
804   @Override
805   public Collection<V> values() {
806     return super.values();
807   }
808 
809   @LazyInit @CheckForNull private transient Map<R, Map<C, V>> rowMap;
810 
811   @Override
812   public Map<R, Map<C, V>> rowMap() {
813     Map<R, Map<C, V>> result = rowMap;
814     return (result == null) ? rowMap = createRowMap() : result;
815   }
816 
817   Map<R, Map<C, V>> createRowMap() {
818     return new RowMap();
819   }
820 
821   @WeakOuter
822   class RowMap extends ViewCachingAbstractMap<R, Map<C, V>> {
823     @Override
824     public boolean containsKey(@CheckForNull Object key) {
825       return containsRow(key);
826     }
827 
828     // performing cast only when key is in backing map and has the correct type
829     @SuppressWarnings("unchecked")
830     @Override
831     @CheckForNull
832     public Map<C, V> get(@CheckForNull Object key) {
833       // requireNonNull is safe because of the containsRow check.
834       return containsRow(key) ? row((R) requireNonNull(key)) : null;
835     }
836 
837     @Override
838     @CheckForNull
839     public Map<C, V> remove(@CheckForNull Object key) {
840       return (key == null) ? null : backingMap.remove(key);
841     }
842 
843     @Override
844     protected Set<Entry<R, Map<C, V>>> createEntrySet() {
845       return new EntrySet();
846     }
847 
848     @WeakOuter
849     private final class EntrySet extends TableSet<Entry<R, Map<C, V>>> {
850       @Override
851       public Iterator<Entry<R, Map<C, V>>> iterator() {
852         return Maps.asMapEntryIterator(
853             backingMap.keySet(),
854             new Function<R, Map<C, V>>() {
855               @Override
856               public Map<C, V> apply(R rowKey) {
857                 return row(rowKey);
858               }
859             });
860       }
861 
862       @Override
863       public int size() {
864         return backingMap.size();
865       }
866 
867       @Override
868       public boolean contains(@CheckForNull Object obj) {
869         if (obj instanceof Entry) {
870           Entry<?, ?> entry = (Entry<?, ?>) obj;
871           return entry.getKey() != null
872               && entry.getValue() instanceof Map
873               && Collections2.safeContains(backingMap.entrySet(), entry);
874         }
875         return false;
876       }
877 
878       @Override
879       public boolean remove(@CheckForNull Object obj) {
880         if (obj instanceof Entry) {
881           Entry<?, ?> entry = (Entry<?, ?>) obj;
882           return entry.getKey() != null
883               && entry.getValue() instanceof Map
884               && backingMap.entrySet().remove(entry);
885         }
886         return false;
887       }
888     }
889   }
890 
891   @LazyInit @CheckForNull private transient ColumnMap columnMap;
892 
893   @Override
894   public Map<C, Map<R, V>> columnMap() {
895     ColumnMap result = columnMap;
896     return (result == null) ? columnMap = new ColumnMap() : result;
897   }
898 
899   @WeakOuter
900   private class ColumnMap extends ViewCachingAbstractMap<C, Map<R, V>> {
901     // The cast to C occurs only when the key is in the map, implying that it
902     // has the correct type.
903     @SuppressWarnings("unchecked")
904     @Override
905     @CheckForNull
906     public Map<R, V> get(@CheckForNull Object key) {
907       // requireNonNull is safe because of the containsColumn check.
908       return containsColumn(key) ? column((C) requireNonNull(key)) : null;
909     }
910 
911     @Override
912     public boolean containsKey(@CheckForNull Object key) {
913       return containsColumn(key);
914     }
915 
916     @Override
917     @CheckForNull
918     public Map<R, V> remove(@CheckForNull Object key) {
919       return containsColumn(key) ? removeColumn(key) : null;
920     }
921 
922     @Override
923     public Set<Entry<C, Map<R, V>>> createEntrySet() {
924       return new ColumnMapEntrySet();
925     }
926 
927     @Override
928     public Set<C> keySet() {
929       return columnKeySet();
930     }
931 
932     @Override
933     Collection<Map<R, V>> createValues() {
934       return new ColumnMapValues();
935     }
936 
937     @WeakOuter
938     private final class ColumnMapEntrySet extends TableSet<Entry<C, Map<R, V>>> {
939       @Override
940       public Iterator<Entry<C, Map<R, V>>> iterator() {
941         return Maps.asMapEntryIterator(
942             columnKeySet(),
943             new Function<C, Map<R, V>>() {
944               @Override
945               public Map<R, V> apply(C columnKey) {
946                 return column(columnKey);
947               }
948             });
949       }
950 
951       @Override
952       public int size() {
953         return columnKeySet().size();
954       }
955 
956       @Override
957       public boolean contains(@CheckForNull Object obj) {
958         if (obj instanceof Entry) {
959           Entry<?, ?> entry = (Entry<?, ?>) obj;
960           if (containsColumn(entry.getKey())) {
961             // requireNonNull is safe because of the containsColumn check.
962             return requireNonNull(get(entry.getKey())).equals(entry.getValue());
963           }
964         }
965         return false;
966       }
967 
968       @Override
969       public boolean remove(@CheckForNull Object obj) {
970         /*
971          * `o instanceof Entry` is guaranteed by `contains`, but we check it here to satisfy our
972          * nullness checker.
973          */
974         if (contains(obj) && obj instanceof Entry) {
975           Entry<?, ?> entry = (Entry<?, ?>) obj;
976           removeColumn(entry.getKey());
977           return true;
978         }
979         return false;
980       }
981 
982       @Override
983       public boolean removeAll(Collection<?> c) {
984         /*
985          * We can't inherit the normal implementation (which calls
986          * Sets.removeAllImpl(Set, *Collection*)) because, under some
987          * circumstances, it attempts to call columnKeySet().iterator().remove,
988          * which is unsupported.
989          */
990         checkNotNull(c);
991         return Sets.removeAllImpl(this, c.iterator());
992       }
993 
994       @Override
995       public boolean retainAll(Collection<?> c) {
996         checkNotNull(c);
997         boolean changed = false;
998         for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
999           if (!c.contains(Maps.immutableEntry(columnKey, column(columnKey)))) {
1000             removeColumn(columnKey);
1001             changed = true;
1002           }
1003         }
1004         return changed;
1005       }
1006     }
1007 
1008     @WeakOuter
1009     private class ColumnMapValues extends Maps.Values<C, Map<R, V>> {
1010       ColumnMapValues() {
1011         super(ColumnMap.this);
1012       }
1013 
1014       @Override
1015       public boolean remove(@CheckForNull Object obj) {
1016         for (Entry<C, Map<R, V>> entry : ColumnMap.this.entrySet()) {
1017           if (entry.getValue().equals(obj)) {
1018             removeColumn(entry.getKey());
1019             return true;
1020           }
1021         }
1022         return false;
1023       }
1024 
1025       @Override
1026       public boolean removeAll(Collection<?> c) {
1027         checkNotNull(c);
1028         boolean changed = false;
1029         for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
1030           if (c.contains(column(columnKey))) {
1031             removeColumn(columnKey);
1032             changed = true;
1033           }
1034         }
1035         return changed;
1036       }
1037 
1038       @Override
1039       public boolean retainAll(Collection<?> c) {
1040         checkNotNull(c);
1041         boolean changed = false;
1042         for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
1043           if (!c.contains(column(columnKey))) {
1044             removeColumn(columnKey);
1045             changed = true;
1046           }
1047         }
1048         return changed;
1049       }
1050     }
1051   }
1052 
1053   private static final long serialVersionUID = 0;
1054 }
1055