11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2009 Google Inc.
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License.
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkArgument;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkNotNull;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.VisibleForTesting;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Function;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Objects;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collections;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Comparator;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.List;
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map;
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable;
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.concurrent.Immutable;
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * An implementation of {@link ImmutableTable} holding an arbitrary number of
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * cells.
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author gak@google.com (Gregory Kick)
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertabstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> {
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final ImmutableSet<Cell<R, C, V>> cellSet;
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private RegularImmutableTable(ImmutableSet<Cell<R, C, V>> cellSet) {
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.cellSet = cellSet;
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final Function<Cell<Object, Object, Object>, Object>
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      GET_VALUE_FUNCTION =
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          new Function<Cell<Object, Object, Object>, Object>() {
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            @Override public Object apply(Cell<Object, Object, Object> from) {
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return from.getValue();
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          };
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @SuppressWarnings("unchecked")
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private Function<Cell<R, C, V>, V> getValueFunction() {
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (Function) GET_VALUE_FUNCTION;
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable private transient volatile ImmutableList<V> valueList;
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override public final ImmutableCollection<V> values() {
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ImmutableList<V> result = valueList;
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (result == null) {
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      valueList = result = ImmutableList.copyOf(
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Iterables.transform(cellSet(), getValueFunction()));
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return result;
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override public final int size() {
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return cellSet().size();
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override public final boolean containsValue(@Nullable Object value) {
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return values().contains(value);
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override public final boolean isEmpty() {
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return false;
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override public final ImmutableSet<Cell<R, C, V>> cellSet() {
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return cellSet;
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final <R, C, V> RegularImmutableTable<R, C, V> forCells(
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      List<Cell<R, C, V>> cells,
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Nullable final Comparator<? super R> rowComparator,
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Nullable final Comparator<? super C> columnComparator) {
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(cells);
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (rowComparator != null || columnComparator != null) {
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      /*
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * This sorting logic leads to a cellSet() ordering that may not be
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * expected and that isn't documented in the Javadoc. If a row Comparator
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * is provided, cellSet() iterates across the columns in the first row,
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * the columns in the second row, etc. If a column Comparator is provided
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * but a row Comparator isn't, cellSet() iterates across the rows in the
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * first column, the rows in the second column, etc.
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       */
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Comparator<Cell<R, C, V>> comparator = new Comparator<Cell<R, C, V>>() {
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override public int compare(Cell<R, C, V> cell1, Cell<R, C, V> cell2) {
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          int rowCompare = (rowComparator == null) ? 0
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            : rowComparator.compare(cell1.getRowKey(), cell2.getRowKey());
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (rowCompare != 0) {
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return rowCompare;
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return (columnComparator == null) ? 0
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              : columnComparator.compare(
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  cell1.getColumnKey(), cell2.getColumnKey());
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      };
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Collections.sort(cells, comparator);
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return forCellsInternal(cells, rowComparator, columnComparator);
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final <R, C, V> RegularImmutableTable<R, C, V> forCells(
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Iterable<Cell<R, C, V>> cells) {
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return forCellsInternal(cells, null, null);
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * A factory that chooses the most space-efficient representation of the
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * table.
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final <R, C, V> RegularImmutableTable<R, C, V>
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      forCellsInternal(Iterable<Cell<R, C, V>> cells,
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Nullable Comparator<? super R> rowComparator,
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Nullable Comparator<? super C> columnComparator) {
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ImmutableSet.Builder<Cell<R, C, V>> cellSetBuilder = ImmutableSet.builder();
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ImmutableSet.Builder<R> rowSpaceBuilder = ImmutableSet.builder();
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ImmutableSet.Builder<C> columnSpaceBuilder = ImmutableSet.builder();
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (Cell<R, C, V> cell : cells) {
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      cellSetBuilder.add(cell);
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      rowSpaceBuilder.add(cell.getRowKey());
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      columnSpaceBuilder.add(cell.getColumnKey());
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ImmutableSet<Cell<R, C, V>> cellSet = cellSetBuilder.build();
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ImmutableSet<R> rowSpace = rowSpaceBuilder.build();
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (rowComparator != null) {
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      List<R> rowList = Lists.newArrayList(rowSpace);
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Collections.sort(rowList, rowComparator);
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      rowSpace = ImmutableSet.copyOf(rowList);
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ImmutableSet<C> columnSpace = columnSpaceBuilder.build();
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (columnComparator != null) {
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      List<C> columnList = Lists.newArrayList(columnSpace);
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Collections.sort(columnList, columnComparator);
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      columnSpace = ImmutableSet.copyOf(columnList);
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // use a dense table if more than half of the cells have values
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // TODO(gak): tune this condition based on empirical evidence
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (cellSet.size() > ((rowSpace.size() * columnSpace.size()) / 2 )) ?
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new DenseImmutableTable<R, C, V>(cellSet, rowSpace, columnSpace) :
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new SparseImmutableTable<R, C, V>(cellSet, rowSpace, columnSpace);
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * A {@code RegularImmutableTable} optimized for sparse data.
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Immutable
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @VisibleForTesting
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class SparseImmutableTable<R, C, V>
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends RegularImmutableTable<R, C, V> {
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final ImmutableMap<R, Map<C, V>> rowMap;
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final ImmutableMap<C, Map<R, V>> columnMap;
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Creates a {@link Map} over the key space with
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * {@link ImmutableMap.Builder}s ready for values.
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final <A, B, V> Map<A, ImmutableMap.Builder<B, V>>
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        makeIndexBuilder(ImmutableSet<A> keySpace) {
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Map<A, ImmutableMap.Builder<B, V>> indexBuilder = Maps.newLinkedHashMap();
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (A key : keySpace) {
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        indexBuilder.put(key, ImmutableMap.<B, V>builder());
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return indexBuilder;
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Builds the value maps of the index and creates an immutable copy of the
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * map.
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final <A, B, V> ImmutableMap<A, Map<B, V>> buildIndex(
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Map<A, ImmutableMap.Builder<B, V>> indexBuilder) {
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return ImmutableMap.copyOf(Maps.transformValues(indexBuilder,
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          new Function<ImmutableMap.Builder<B, V>, Map<B, V>>() {
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            @Override public Map<B, V> apply(ImmutableMap.Builder<B, V> from) {
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return from.build();
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }));
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    SparseImmutableTable(ImmutableSet<Cell<R, C, V>> cellSet,
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ImmutableSet<R> rowSpace, ImmutableSet<C> columnSpace) {
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(cellSet);
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Map<R, ImmutableMap.Builder<C, V>> rowIndexBuilder
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          = makeIndexBuilder(rowSpace);
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Map<C, ImmutableMap.Builder<R, V>> columnIndexBuilder
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          = makeIndexBuilder(columnSpace);
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (Cell<R, C, V> cell : cellSet) {
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        R rowKey = cell.getRowKey();
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        C columnKey = cell.getColumnKey();
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        V value = cell.getValue();
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        rowIndexBuilder.get(rowKey).put(columnKey, value);
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        columnIndexBuilder.get(columnKey).put(rowKey, value);
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.rowMap = buildIndex(rowIndexBuilder);
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.columnMap = buildIndex(columnIndexBuilder);
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public ImmutableMap<R, V> column(C columnKey) {
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      checkNotNull(columnKey);
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // value maps are guaranteed to be immutable maps
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Objects.firstNonNull((ImmutableMap<R, V>) columnMap.get(columnKey),
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ImmutableMap.<R, V>of());
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public ImmutableSet<C> columnKeySet() {
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return columnMap.keySet();
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public ImmutableMap<C, Map<R, V>> columnMap() {
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return columnMap;
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public ImmutableMap<C, V> row(R rowKey) {
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      checkNotNull(rowKey);
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // value maps are guaranteed to be immutable maps
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Objects.firstNonNull((ImmutableMap<C, V>) rowMap.get(rowKey),
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ImmutableMap.<C, V>of());
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public ImmutableSet<R> rowKeySet() {
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return rowMap.keySet();
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public ImmutableMap<R, Map<C, V>> rowMap() {
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return rowMap;
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean contains(@Nullable Object rowKey,
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Nullable Object columnKey) {
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Map<C, V> row = rowMap.get(rowKey);
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (row != null) && row.containsKey(columnKey);
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean containsColumn(@Nullable Object columnKey) {
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return columnMap.containsKey(columnKey);
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean containsRow(@Nullable Object rowKey) {
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return rowMap.containsKey(rowKey);
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public V get(@Nullable Object rowKey,
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Nullable Object columnKey) {
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Map<C, V> row = rowMap.get(rowKey);
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (row == null) ? null : row.get(columnKey);
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * A {@code RegularImmutableTable} optimized for dense data.
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Immutable @VisibleForTesting
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class DenseImmutableTable<R, C, V>
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends RegularImmutableTable<R, C, V> {
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final ImmutableBiMap<R, Integer> rowKeyToIndex;
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final ImmutableBiMap<C, Integer> columnKeyToIndex;
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final V[][] values;
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static <E> ImmutableBiMap<E, Integer> makeIndex(
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ImmutableSet<E> set) {
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ImmutableBiMap.Builder<E, Integer> indexBuilder =
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ImmutableBiMap.builder();
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int i = 0;
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (E key : set) {
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        indexBuilder.put(key, i);
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        i++;
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return indexBuilder.build();
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    DenseImmutableTable(ImmutableSet<Cell<R, C, V>> cellSet,
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ImmutableSet<R> rowSpace, ImmutableSet<C> columnSpace) {
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(cellSet);
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @SuppressWarnings("unchecked")
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      V[][] array = (V[][]) new Object[rowSpace.size()][columnSpace.size()];
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.values = array;
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.rowKeyToIndex = makeIndex(rowSpace);
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.columnKeyToIndex = makeIndex(columnSpace);
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (Cell<R, C, V> cell : cellSet) {
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        R rowKey = cell.getRowKey();
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        C columnKey = cell.getColumnKey();
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int rowIndex = rowKeyToIndex.get(rowKey);
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int columnIndex = columnKeyToIndex.get(columnKey);
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        V existingValue = values[rowIndex][columnIndex];
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        checkArgument(existingValue == null, "duplicate key: (%s, %s)", rowKey,
3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            columnKey);
3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        values[rowIndex][columnIndex] = cell.getValue();
3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public ImmutableMap<R, V> column(C columnKey) {
3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      checkNotNull(columnKey);
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Integer columnIndexInteger = columnKeyToIndex.get(columnKey);
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (columnIndexInteger == null) {
3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return ImmutableMap.of();
3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else {
3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // unbox only once
3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int columnIndex = columnIndexInteger;
3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ImmutableMap.Builder<R, V> columnBuilder = ImmutableMap.builder();
3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (int i = 0; i < values.length; i++) {
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          V value = values[i][columnIndex];
3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (value != null) {
3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            columnBuilder.put(rowKeyToIndex.inverse().get(i), value);
3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return columnBuilder.build();
3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public ImmutableSet<C> columnKeySet() {
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return columnKeyToIndex.keySet();
3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private transient volatile ImmutableMap<C, Map<R, V>> columnMap;
3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private ImmutableMap<C, Map<R, V>> makeColumnMap() {
3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ImmutableMap.Builder<C, Map<R, V>> columnMapBuilder =
3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ImmutableMap.builder();
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int c = 0; c < columnKeyToIndex.size(); c++) {
3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ImmutableMap.Builder<R, V> rowMapBuilder = ImmutableMap.builder();
3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (int r = 0; r < rowKeyToIndex.size(); r++) {
3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          V value = values[r][c];
3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (value != null) {
3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            rowMapBuilder.put(rowKeyToIndex.inverse().get(r), value);
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        columnMapBuilder.put(columnKeyToIndex.inverse().get(c),
3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            rowMapBuilder.build());
3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return columnMapBuilder.build();
3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public ImmutableMap<C, Map<R, V>> columnMap() {
3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ImmutableMap<C, Map<R, V>> result = columnMap;
3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (result == null) {
3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        columnMap = result = makeColumnMap();
3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return result;
3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean contains(@Nullable Object rowKey,
3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Nullable Object columnKey) {
3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (get(rowKey, columnKey) != null);
3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean containsColumn(@Nullable Object columnKey) {
3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return columnKeyToIndex.containsKey(columnKey);
3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean containsRow(@Nullable Object rowKey) {
3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return rowKeyToIndex.containsKey(rowKey);
3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public V get(@Nullable Object rowKey,
3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Nullable Object columnKey) {
3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Integer rowIndex = rowKeyToIndex.get(rowKey);
3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Integer columnIndex = columnKeyToIndex.get(columnKey);
3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return ((rowIndex == null) || (columnIndex == null)) ? null
3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          : values[rowIndex][columnIndex];
3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public ImmutableMap<C, V> row(R rowKey) {
3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      checkNotNull(rowKey);
3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Integer rowIndex = rowKeyToIndex.get(rowKey);
3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (rowIndex == null) {
3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return ImmutableMap.of();
3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else {
3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ImmutableMap.Builder<C, V> rowBuilder = ImmutableMap.builder();
3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        V[] row = values[rowIndex];
3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (int r = 0; r < row.length; r++) {
3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          V value = row[r];
3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (value != null) {
3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            rowBuilder.put(columnKeyToIndex.inverse().get(r), value);
3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return rowBuilder.build();
3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public ImmutableSet<R> rowKeySet() {
4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return rowKeyToIndex.keySet();
4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private transient volatile ImmutableMap<R, Map<C, V>> rowMap;
4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private ImmutableMap<R, Map<C, V>> makeRowMap() {
4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ImmutableMap.Builder<R, Map<C, V>> rowMapBuilder = ImmutableMap.builder();
4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int r = 0; r < values.length; r++) {
4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        V[] row = values[r];
4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ImmutableMap.Builder<C, V> columnMapBuilder = ImmutableMap.builder();
4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (int c = 0; c < row.length; c++) {
4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          V value = row[c];
4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (value != null) {
4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            columnMapBuilder.put(columnKeyToIndex.inverse().get(c), value);
4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
4181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
4191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        rowMapBuilder.put(rowKeyToIndex.inverse().get(r),
4201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            columnMapBuilder.build());
4211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return rowMapBuilder.build();
4231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public ImmutableMap<R, Map<C, V>> rowMap() {
4261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ImmutableMap<R, Map<C, V>> result = rowMap;
4271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (result == null) {
4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        rowMap = result = makeRowMap();
4291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return result;
4311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
434