org.weakref.jmx.internal.guava.collect.DenseImmutableTable Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jmxutils Show documentation
Show all versions of jmxutils Show documentation
Exporting JMX mbeans made easy
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.weakref.jmx.internal.guava.collect;
import static org.weakref.jmx.internal.guava.base.Preconditions.checkArgument;
import org.weakref.jmx.internal.guava.annotations.GwtCompatible;
import java.util.Map;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
* A {@code RegularImmutableTable} optimized for dense data.
*/
@GwtCompatible
@Immutable
final class DenseImmutableTable
extends RegularImmutableTable {
private final ImmutableMap rowKeyToIndex;
private final ImmutableMap columnKeyToIndex;
private final ImmutableMap> rowMap;
private final ImmutableMap> columnMap;
private final int[] rowCounts;
private final int[] columnCounts;
private final V[][] values;
private final int[] iterationOrderRow;
private final int[] iterationOrderColumn;
private static ImmutableMap makeIndex(ImmutableSet set) {
ImmutableMap.Builder indexBuilder = ImmutableMap.builder();
int i = 0;
for (E key : set) {
indexBuilder.put(key, i);
i++;
}
return indexBuilder.build();
}
DenseImmutableTable(ImmutableList> cellList,
ImmutableSet rowSpace, ImmutableSet columnSpace) {
@SuppressWarnings("unchecked")
V[][] array = (V[][]) new Object[rowSpace.size()][columnSpace.size()];
this.values = array;
this.rowKeyToIndex = makeIndex(rowSpace);
this.columnKeyToIndex = makeIndex(columnSpace);
rowCounts = new int[rowKeyToIndex.size()];
columnCounts = new int[columnKeyToIndex.size()];
int[] iterationOrderRow = new int[cellList.size()];
int[] iterationOrderColumn = new int[cellList.size()];
for (int i = 0; i < cellList.size(); i++) {
Cell cell = cellList.get(i);
R rowKey = cell.getRowKey();
C columnKey = cell.getColumnKey();
int rowIndex = rowKeyToIndex.get(rowKey);
int columnIndex = columnKeyToIndex.get(columnKey);
V existingValue = values[rowIndex][columnIndex];
checkArgument(existingValue == null, "duplicate key: (%s, %s)", rowKey, columnKey);
values[rowIndex][columnIndex] = cell.getValue();
rowCounts[rowIndex]++;
columnCounts[columnIndex]++;
iterationOrderRow[i] = rowIndex;
iterationOrderColumn[i] = columnIndex;
}
this.iterationOrderRow = iterationOrderRow;
this.iterationOrderColumn = iterationOrderColumn;
this.rowMap = new RowMap();
this.columnMap = new ColumnMap();
}
/**
* An immutable map implementation backed by an indexed nullable array.
*/
private abstract static class ImmutableArrayMap extends ImmutableMap {
private final int size;
ImmutableArrayMap(int size) {
this.size = size;
}
abstract ImmutableMap keyToIndex();
// True if getValue never returns null.
private boolean isFull() {
return size == keyToIndex().size();
}
K getKey(int index) {
return keyToIndex().keySet().asList().get(index);
}
@Nullable abstract V getValue(int keyIndex);
@Override
ImmutableSet createKeySet() {
return isFull() ? keyToIndex().keySet() : super.createKeySet();
}
@Override
public int size() {
return size;
}
@Override
public V get(@Nullable Object key) {
Integer keyIndex = keyToIndex().get(key);
return (keyIndex == null) ? null : getValue(keyIndex);
}
@Override
ImmutableSet> createEntrySet() {
return new ImmutableMapEntrySet() {
@Override ImmutableMap map() {
return ImmutableArrayMap.this;
}
@Override
public UnmodifiableIterator> iterator() {
return new AbstractIterator>() {
private int index = -1;
private final int maxIndex = keyToIndex().size();
@Override
protected Entry computeNext() {
for (index++; index < maxIndex; index++) {
V value = getValue(index);
if (value != null) {
return Maps.immutableEntry(getKey(index), value);
}
}
return endOfData();
}
};
}
};
}
}
private final class Row extends ImmutableArrayMap {
private final int rowIndex;
Row(int rowIndex) {
super(rowCounts[rowIndex]);
this.rowIndex = rowIndex;
}
@Override
ImmutableMap keyToIndex() {
return columnKeyToIndex;
}
@Override
V getValue(int keyIndex) {
return values[rowIndex][keyIndex];
}
@Override
boolean isPartialView() {
return true;
}
}
private final class Column extends ImmutableArrayMap {
private final int columnIndex;
Column(int columnIndex) {
super(columnCounts[columnIndex]);
this.columnIndex = columnIndex;
}
@Override
ImmutableMap keyToIndex() {
return rowKeyToIndex;
}
@Override
V getValue(int keyIndex) {
return values[keyIndex][columnIndex];
}
@Override
boolean isPartialView() {
return true;
}
}
private final class RowMap extends ImmutableArrayMap> {
private RowMap() {
super(rowCounts.length);
}
@Override
ImmutableMap keyToIndex() {
return rowKeyToIndex;
}
@Override
Map getValue(int keyIndex) {
return new Row(keyIndex);
}
@Override
boolean isPartialView() {
return false;
}
}
private final class ColumnMap extends ImmutableArrayMap> {
private ColumnMap() {
super(columnCounts.length);
}
@Override
ImmutableMap keyToIndex() {
return columnKeyToIndex;
}
@Override
Map getValue(int keyIndex) {
return new Column(keyIndex);
}
@Override
boolean isPartialView() {
return false;
}
}
@Override public ImmutableMap> columnMap() {
return columnMap;
}
@Override
public ImmutableMap> rowMap() {
return rowMap;
}
@Override public V get(@Nullable Object rowKey,
@Nullable Object columnKey) {
Integer rowIndex = rowKeyToIndex.get(rowKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
return ((rowIndex == null) || (columnIndex == null)) ? null
: values[rowIndex][columnIndex];
}
@Override
public int size() {
return iterationOrderRow.length;
}
@Override
Cell getCell(int index) {
int rowIndex = iterationOrderRow[index];
int columnIndex = iterationOrderColumn[index];
R rowKey = rowKeySet().asList().get(rowIndex);
C columnKey = columnKeySet().asList().get(columnIndex);
V value = values[rowIndex][columnIndex];
return cellOf(rowKey, columnKey, value);
}
@Override
V getValue(int index) {
return values[iterationOrderRow[index]][iterationOrderColumn[index]];
}
}
|