1
2
3
4
5
6
7
8
9
10
11
12
13
14
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.base.Objects;
23
24 import java.util.Comparator;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28
29 import javax.annotation.Nullable;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 @GwtCompatible
47
48 public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
49 private static final ImmutableTable<Object, Object, Object> EMPTY
50 = new SparseImmutableTable<Object, Object, Object>(
51 ImmutableList.<Cell<Object, Object, Object>>of(),
52 ImmutableSet.of(), ImmutableSet.of());
53
54
55 @SuppressWarnings("unchecked")
56 public static <R, C, V> ImmutableTable<R, C, V> of() {
57 return (ImmutableTable<R, C, V>) EMPTY;
58 }
59
60
61 public static <R, C, V> ImmutableTable<R, C, V> of(R rowKey,
62 C columnKey, V value) {
63 return new SingletonImmutableTable<R, C, V>(rowKey, columnKey, value);
64 }
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 public static <R, C, V> ImmutableTable<R, C, V> copyOf(
81 Table<? extends R, ? extends C, ? extends V> table) {
82 if (table instanceof ImmutableTable) {
83 @SuppressWarnings("unchecked")
84 ImmutableTable<R, C, V> parameterizedTable
85 = (ImmutableTable<R, C, V>) table;
86 return parameterizedTable;
87 } else {
88 int size = table.size();
89 switch (size) {
90 case 0:
91 return of();
92 case 1:
93 Cell<? extends R, ? extends C, ? extends V> onlyCell
94 = Iterables.getOnlyElement(table.cellSet());
95 return ImmutableTable.<R, C, V>of(onlyCell.getRowKey(),
96 onlyCell.getColumnKey(), onlyCell.getValue());
97 default:
98 ImmutableSet.Builder<Cell<R, C, V>> cellSetBuilder
99 = ImmutableSet.builder();
100 for (Cell<? extends R, ? extends C, ? extends V> cell :
101 table.cellSet()) {
102
103
104
105
106 cellSetBuilder.add(cellOf((R) cell.getRowKey(),
107 (C) cell.getColumnKey(), (V) cell.getValue()));
108 }
109 return RegularImmutableTable.forCells(cellSetBuilder.build());
110 }
111 }
112 }
113
114
115
116
117
118 public static <R, C, V> Builder<R, C, V> builder() {
119 return new Builder<R, C, V>();
120 }
121
122
123
124
125
126 static <R, C, V> Cell<R, C, V> cellOf(R rowKey, C columnKey, V value) {
127 return Tables.immutableCell(checkNotNull(rowKey), checkNotNull(columnKey),
128 checkNotNull(value));
129 }
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157 public static final class Builder<R, C, V> {
158 private final List<Cell<R, C, V>> cells = Lists.newArrayList();
159 private Comparator<? super R> rowComparator;
160 private Comparator<? super C> columnComparator;
161
162
163
164
165
166 public Builder() {}
167
168
169
170
171 public Builder<R, C, V> orderRowsBy(Comparator<? super R> rowComparator) {
172 this.rowComparator = checkNotNull(rowComparator);
173 return this;
174 }
175
176
177
178
179 public Builder<R, C, V> orderColumnsBy(
180 Comparator<? super C> columnComparator) {
181 this.columnComparator = checkNotNull(columnComparator);
182 return this;
183 }
184
185
186
187
188
189
190 public Builder<R, C, V> put(R rowKey, C columnKey, V value) {
191 cells.add(cellOf(rowKey, columnKey, value));
192 return this;
193 }
194
195
196
197
198
199
200 public Builder<R, C, V> put(
201 Cell<? extends R, ? extends C, ? extends V> cell) {
202 if (cell instanceof Tables.ImmutableCell) {
203 checkNotNull(cell.getRowKey());
204 checkNotNull(cell.getColumnKey());
205 checkNotNull(cell.getValue());
206 @SuppressWarnings("unchecked")
207 Cell<R, C, V> immutableCell = (Cell<R, C, V>) cell;
208 cells.add(immutableCell);
209 } else {
210 put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
211 }
212 return this;
213 }
214
215
216
217
218
219
220
221
222 public Builder<R, C, V> putAll(
223 Table<? extends R, ? extends C, ? extends V> table) {
224 for (Cell<? extends R, ? extends C, ? extends V> cell : table.cellSet()) {
225 put(cell);
226 }
227 return this;
228 }
229
230
231
232
233
234
235 public ImmutableTable<R, C, V> build() {
236 int size = cells.size();
237 switch (size) {
238 case 0:
239 return of();
240 case 1:
241 return new SingletonImmutableTable<R, C, V>(
242 Iterables.getOnlyElement(cells));
243 default:
244 return RegularImmutableTable.forCells(
245 cells, rowComparator, columnComparator);
246 }
247 }
248 }
249
250 ImmutableTable() {}
251
252 @Override public ImmutableSet<Cell<R, C, V>> cellSet() {
253 return (ImmutableSet<Cell<R, C, V>>) super.cellSet();
254 }
255
256 @Override
257 abstract ImmutableSet<Cell<R, C, V>> createCellSet();
258
259 @Override
260 final UnmodifiableIterator<Cell<R, C, V>> cellIterator() {
261 throw new AssertionError("should never be called");
262 }
263
264 @Override
265 public ImmutableCollection<V> values() {
266 return (ImmutableCollection<V>) super.values();
267 }
268
269 @Override
270 abstract ImmutableCollection<V> createValues();
271
272 @Override
273 final Iterator<V> valuesIterator() {
274 throw new AssertionError("should never be called");
275 }
276
277
278
279
280
281
282 @Override public ImmutableMap<R, V> column(C columnKey) {
283 checkNotNull(columnKey);
284 return Objects.firstNonNull(
285 (ImmutableMap<R, V>) columnMap().get(columnKey),
286 ImmutableMap.<R, V>of());
287 }
288
289 @Override public ImmutableSet<C> columnKeySet() {
290 return columnMap().keySet();
291 }
292
293
294
295
296
297
298
299 @Override public abstract ImmutableMap<C, Map<R, V>> columnMap();
300
301
302
303
304
305
306 @Override public ImmutableMap<C, V> row(R rowKey) {
307 checkNotNull(rowKey);
308 return Objects.firstNonNull(
309 (ImmutableMap<C, V>) rowMap().get(rowKey),
310 ImmutableMap.<C, V>of());
311 }
312
313 @Override public ImmutableSet<R> rowKeySet() {
314 return rowMap().keySet();
315 }
316
317
318
319
320
321
322
323 @Override public abstract ImmutableMap<R, Map<C, V>> rowMap();
324
325 @Override
326 public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
327 return get(rowKey, columnKey) != null;
328 }
329
330 @Override
331 public boolean containsValue(@Nullable Object value) {
332 return values().contains(value);
333 }
334
335
336
337
338
339
340
341 @Deprecated @Override public final void clear() {
342 throw new UnsupportedOperationException();
343 }
344
345
346
347
348
349
350
351 @Deprecated @Override public final V put(R rowKey, C columnKey, V value) {
352 throw new UnsupportedOperationException();
353 }
354
355
356
357
358
359
360
361 @Deprecated @Override public final void putAll(
362 Table<? extends R, ? extends C, ? extends V> table) {
363 throw new UnsupportedOperationException();
364 }
365
366
367
368
369
370
371
372 @Deprecated @Override public final V remove(Object rowKey, Object columnKey) {
373 throw new UnsupportedOperationException();
374 }
375 }