public AggregationIterator( List<NamedExpression> groupingExpressions, List<Attribute> inputAttributes, List<AggregateExpression> aggregateExpressions, List<Attribute> aggregateAttributes, int initialInputBufferOffset, List<NamedExpression> resultExpressions, BiFunction<List<Expression>, List<Attribute>, Supplier<MutableProjection>> newMutableProjection) { this.groupingExpressions = groupingExpressions; this.inputAttributes = inputAttributes; this.aggregateExpressions = aggregateExpressions; this.aggregateAttributes = aggregateAttributes; this.initialInputBufferOffset = initialInputBufferOffset; this.resultExpressions = resultExpressions; this.newMutableProjection = newMutableProjection; this.modes = aggregateExpressions.stream().map(e -> e.mode).distinct().collect(Collectors.toSet()); checkArgs(); this.aggregateFunctions = initializeAggregateFunctions(aggregateExpressions); this.expressionAggInitialProjection = newMutableProjection.apply( flatMapToList(aggregateFunctions, AggregateFunction::initialValues), null ).get(); this.processRow = generateProcessRow(aggregateExpressions, aggregateFunctions, inputAttributes); this.groupingProjection = UnsafeProjection.create(groupingExpressions, inputAttributes); this.groupingAttributes = mapToList(groupingExpressions, NamedExpression::toAttribute); this.generateOutput = generateResultProjection(); }