Coverage Summary for Class: TableCollectors (com.google.common.collect)
| Class | Method, % | Line, % |
|---|---|---|
| TableCollectors | 0% (0/14) | 0% (0/43) |
| TableCollectors$ImmutableTableCollectorState | 0% (0/5) | 0% (0/15) |
| TableCollectors$MutableCell | 0% (0/5) | 0% (0/9) |
| Total | 0% (0/24) | 0% (0/67) |
1 /* 2 * Copyright (C) 2009 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 21 import com.google.common.annotations.GwtCompatible; 22 import com.google.common.collect.Tables.AbstractCell; 23 import java.util.ArrayList; 24 import java.util.List; 25 import java.util.function.BinaryOperator; 26 import java.util.function.Function; 27 import java.util.function.Supplier; 28 import java.util.stream.Collector; 29 30 /** Collectors utilities for {@code common.collect.Table} internals. */ 31 @GwtCompatible 32 final class TableCollectors { 33 34 static <T, R, C, V> Collector<T, ?, ImmutableTable<R, C, V>> toImmutableTable( 35 Function<? super T, ? extends R> rowFunction, 36 Function<? super T, ? extends C> columnFunction, 37 Function<? super T, ? extends V> valueFunction) { 38 checkNotNull(rowFunction, "rowFunction"); 39 checkNotNull(columnFunction, "columnFunction"); 40 checkNotNull(valueFunction, "valueFunction"); 41 return Collector.of( 42 (Supplier<ImmutableTable.Builder<R, C, V>>) ImmutableTable.Builder::new, 43 (builder, t) -> 44 builder.put(rowFunction.apply(t), columnFunction.apply(t), valueFunction.apply(t)), 45 ImmutableTable.Builder::combine, 46 ImmutableTable.Builder::build); 47 } 48 49 static <T, R, C, V> Collector<T, ?, ImmutableTable<R, C, V>> toImmutableTable( 50 Function<? super T, ? extends R> rowFunction, 51 Function<? super T, ? extends C> columnFunction, 52 Function<? super T, ? extends V> valueFunction, 53 BinaryOperator<V> mergeFunction) { 54 55 checkNotNull(rowFunction, "rowFunction"); 56 checkNotNull(columnFunction, "columnFunction"); 57 checkNotNull(valueFunction, "valueFunction"); 58 checkNotNull(mergeFunction, "mergeFunction"); 59 60 /* 61 * No mutable Table exactly matches the insertion order behavior of ImmutableTable.Builder, but 62 * the Builder can't efficiently support merging of duplicate values. Getting around this 63 * requires some work. 64 */ 65 66 return Collector.of( 67 () -> new ImmutableTableCollectorState<R, C, V>() 68 /* GWT isn't currently playing nicely with constructor references? */ , 69 (state, input) -> 70 state.put( 71 rowFunction.apply(input), 72 columnFunction.apply(input), 73 valueFunction.apply(input), 74 mergeFunction), 75 (s1, s2) -> s1.combine(s2, mergeFunction), 76 state -> state.toTable()); 77 } 78 79 static <T, R, C, V, I extends Table<R, C, V>> Collector<T, ?, I> toTable( 80 java.util.function.Function<? super T, ? extends R> rowFunction, 81 java.util.function.Function<? super T, ? extends C> columnFunction, 82 java.util.function.Function<? super T, ? extends V> valueFunction, 83 java.util.function.Supplier<I> tableSupplier) { 84 return toTable( 85 rowFunction, 86 columnFunction, 87 valueFunction, 88 (v1, v2) -> { 89 throw new IllegalStateException("Conflicting values " + v1 + " and " + v2); 90 }, 91 tableSupplier); 92 } 93 94 static <T, R, C, V, I extends Table<R, C, V>> Collector<T, ?, I> toTable( 95 java.util.function.Function<? super T, ? extends R> rowFunction, 96 java.util.function.Function<? super T, ? extends C> columnFunction, 97 java.util.function.Function<? super T, ? extends V> valueFunction, 98 BinaryOperator<V> mergeFunction, 99 java.util.function.Supplier<I> tableSupplier) { 100 checkNotNull(rowFunction); 101 checkNotNull(columnFunction); 102 checkNotNull(valueFunction); 103 checkNotNull(mergeFunction); 104 checkNotNull(tableSupplier); 105 return Collector.of( 106 tableSupplier, 107 (table, input) -> 108 mergeTables( 109 table, 110 rowFunction.apply(input), 111 columnFunction.apply(input), 112 valueFunction.apply(input), 113 mergeFunction), 114 (table1, table2) -> { 115 for (Table.Cell<R, C, V> cell2 : table2.cellSet()) { 116 mergeTables( 117 table1, cell2.getRowKey(), cell2.getColumnKey(), cell2.getValue(), mergeFunction); 118 } 119 return table1; 120 }); 121 } 122 123 private static final class ImmutableTableCollectorState<R, C, V> { 124 final List<MutableCell<R, C, V>> insertionOrder = new ArrayList<>(); 125 final Table<R, C, MutableCell<R, C, V>> table = HashBasedTable.create(); 126 127 void put(R row, C column, V value, BinaryOperator<V> merger) { 128 MutableCell<R, C, V> oldCell = table.get(row, column); 129 if (oldCell == null) { 130 MutableCell<R, C, V> cell = new MutableCell<>(row, column, value); 131 insertionOrder.add(cell); 132 table.put(row, column, cell); 133 } else { 134 oldCell.merge(value, merger); 135 } 136 } 137 138 ImmutableTableCollectorState<R, C, V> combine( 139 ImmutableTableCollectorState<R, C, V> other, BinaryOperator<V> merger) { 140 for (MutableCell<R, C, V> cell : other.insertionOrder) { 141 put(cell.getRowKey(), cell.getColumnKey(), cell.getValue(), merger); 142 } 143 return this; 144 } 145 146 ImmutableTable<R, C, V> toTable() { 147 return ImmutableTable.copyOf(insertionOrder); 148 } 149 } 150 151 private static final class MutableCell<R, C, V> extends AbstractCell<R, C, V> { 152 private final R row; 153 private final C column; 154 private V value; 155 156 MutableCell(R row, C column, V value) { 157 this.row = checkNotNull(row, "row"); 158 this.column = checkNotNull(column, "column"); 159 this.value = checkNotNull(value, "value"); 160 } 161 162 @Override 163 public R getRowKey() { 164 return row; 165 } 166 167 @Override 168 public C getColumnKey() { 169 return column; 170 } 171 172 @Override 173 public V getValue() { 174 return value; 175 } 176 177 void merge(V value, BinaryOperator<V> mergeFunction) { 178 checkNotNull(value, "value"); 179 this.value = checkNotNull(mergeFunction.apply(this.value, value), "mergeFunction.apply"); 180 } 181 } 182 183 private static <R, C, V> void mergeTables( 184 Table<R, C, V> table, R row, C column, V value, BinaryOperator<V> mergeFunction) { 185 checkNotNull(value); 186 V oldValue = table.get(row, column); 187 if (oldValue == null) { 188 table.put(row, column, value); 189 } else { 190 V newValue = mergeFunction.apply(oldValue, value); 191 if (newValue == null) { 192 table.remove(row, column); 193 } else { 194 table.put(row, column, newValue); 195 } 196 } 197 } 198 199 private TableCollectors() {} 200 }