/// <summary>
        /// Create the single pass collector.
        /// </summary>
        /// <param name="groupSort">
        /// The <see cref="Sort"/> used to sort the
        /// groups.  The top sorted document within each group
        /// according to groupSort, determines how that group
        /// sorts against other groups.  This must be non-null,
        /// ie, if you want to groupSort by relevance use
        /// <see cref="Sort.RELEVANCE"/>.
        /// </param>
        /// <param name="topNGroups">How many top groups to keep.</param>
        /// <param name="needsScores">
        /// true if the collected documents
        /// require scores, either because relevance is included
        /// in the withinGroupSort or because you plan to pass true
        /// for either GetScores or GetMaxScores to <see cref="GetTopGroups(Sort, int, int, int, bool)"/>
        /// </param>
        /// <param name="lastDocPerGroup">
        /// a <see cref="Filter"/> that marks the
        /// last document in each group.
        /// </param>
        public BlockGroupingCollector(Sort groupSort, int topNGroups, bool needsScores, Filter lastDocPerGroup)
        {
            if (topNGroups < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(topNGroups), "topNGroups must be >= 1 (got " + topNGroups + ")"); // LUCENENET specific - changed from IllegalArgumentException to ArgumentOutOfRangeException (.NET convention)
            }

            groupQueue     = new GroupQueue(this, topNGroups);
            pendingSubDocs = new int[10];
            if (needsScores)
            {
                pendingSubScores = new float[10];
            }

            this.needsScores     = needsScores;
            this.lastDocPerGroup = lastDocPerGroup;
            // TODO: allow null groupSort to mean "by relevance",
            // and specialize it?
            this.groupSort = groupSort;

            this.topNGroups = topNGroups;

            SortField[] sortFields = groupSort.GetSort();
            comparers  = new FieldComparer[sortFields.Length];
            compIDXEnd = comparers.Length - 1;
            reversed   = new int[sortFields.Length];
            for (int i = 0; i < sortFields.Length; i++)
            {
                SortField sortField = sortFields[i];
                comparers[i] = sortField.GetComparer(topNGroups, i);
                reversed[i]  = sortField.IsReverse ? -1 : 1;
            }
        }