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