LinkedListStarTreeTable implements StarTreeTable { @Override public StarTreeTableGroupByStats groupBy(Integer dimension) { Map<Integer, Set<List<Integer>>> uniqueCombinations = new HashMap<Integer, Set<List<Integer>>>(); Map<Integer, Integer> rawCounts = new HashMap<Integer, Integer>(); Map<Integer, Integer> minRecordIds = new HashMap<Integer, Integer>(); int currentRecordId = 0; StarTreeTableRow row = new StarTreeTableRow(dimensionTypes.size(), metricTypes.size()); for (ByteBuffer buffer : list) { fromByteBuffer(buffer, row); Integer value = row.getDimensions().get(dimension); Set<List<Integer>> uniqueSet = uniqueCombinations.get(value); if (uniqueSet == null) { uniqueSet = new HashSet<List<Integer>>(); uniqueCombinations.put(value, uniqueSet); } if (!uniqueSet.contains(row.getDimensions())) { List<Integer> copy = new ArrayList<>(row.getDimensions()); uniqueSet.add(copy); } Integer count = rawCounts.get(value); if (count == null) { count = 0; } rawCounts.put(value, count + 1); Integer existingRecordId = minRecordIds.get(value); if (existingRecordId == null || currentRecordId < existingRecordId) { minRecordIds.put(value, currentRecordId); } currentRecordId++; } StarTreeTableGroupByStats result = new StarTreeTableGroupByStats(); for (Map.Entry<Integer, Set<List<Integer>>> entry : uniqueCombinations.entrySet()) { Integer value = entry.getKey(); Integer uniqueCount = entry.getValue().size(); Integer rawCount = rawCounts.get(value); Integer minRecordId = minRecordIds.get(value); result.setValue(value, rawCount, uniqueCount, minRecordId); } return result; } LinkedListStarTreeTable(List<FieldSpec.DataType> dimensionTypes, List<FieldSpec.DataType> metricTypes); private  LinkedListStarTreeTable(List<ByteBuffer> list,
                                  List<FieldSpec.DataType> dimensionTypes,
                                  List<FieldSpec.DataType> metricTypes); @Override void append(StarTreeTableRow row); @Override int size(); @Override Iterator<StarTreeTableRow> getUniqueCombinations(final List<Integer> excludedDimensions); @Override Iterator<StarTreeTableRow> getAllCombinations(); @Override void sort(final List<Integer> sortDimensions); @Override StarTreeTableGroupByStats groupBy(Integer dimension); @Override StarTreeTable view(Integer startDocumentId, Integer documentCount); @Override void printTable(PrintStream printStream); @Override void close();  }
@Test(dataProvider = "groupByDataProvider") public void testGroupBy(StarTreeTable table, int groupByDimension) { Map<Integer, Integer> rawCounts = new HashMap<Integer, Integer>(); Map<Integer, Set<List<Integer>>> uniqueCombinations = new HashMap<Integer, Set<List<Integer>>>(); for (List<Integer> combination : generateCombinations()) { Integer value = combination.get(groupByDimension); table.append(new StarTreeTableRow(combination, metrics)); Set<List<Integer>> combinationSet = uniqueCombinations.get(value); if (combinationSet == null) { combinationSet = new HashSet<List<Integer>>(); uniqueCombinations.put(value, combinationSet); } combinationSet.add(combination); Integer count = rawCounts.get(value); if (count == null) { count = 0; } rawCounts.put(value, count + 1); } StarTreeTableGroupByStats result = table.groupBy(groupByDimension); Assert.assertEquals(result.getValues(), rawCounts.keySet()); for (Map.Entry<Integer, Integer> entry : rawCounts.entrySet()) { Integer value = entry.getKey(); Integer rawCount = entry.getValue(); Integer uniqueCount = uniqueCombinations.get(value).size(); Assert.assertEquals(result.getRawCount(value), rawCount); Assert.assertEquals(result.getUniqueCount(value), uniqueCount); } }