private void initializeCellSet(int numOfCells, MemStoreSegmentsIterator iterator,
    MemStoreCompactionStrategy.Action action) {
    int numOfCellsAfterCompaction = 0;
    int currentChunkIdx = 0;
    int offsetInCurentChunk = ChunkCreator.SIZEOF_CHUNK_HEADER;
    int numUniqueKeys = 0;
    ExtendedCell prev = null;
    Chunk[] chunks = allocIndexChunks(numOfCells);
    while (iterator.hasNext()) { // the iterator hides the elimination logic for compaction
      boolean alreadyCopied = false;
      ExtendedCell c = iterator.next();
      numOfCellsAfterCompaction++;
      if (c.getChunkId() == ExtendedCell.CELL_NOT_BASED_ON_CHUNK) {
        // CellChunkMap assumes all cells are allocated on MSLAB.
        // Therefore, cells which are not allocated on MSLAB initially,
        // are copied into MSLAB here.
        c = copyCellIntoMSLAB(c, null); // no memstore sizing object to update
        alreadyCopied = true;
      }
      if (offsetInCurentChunk + ClassSize.CELL_CHUNK_MAP_ENTRY > chunks[currentChunkIdx].size) {
        currentChunkIdx++; // continue to the next index chunk
        offsetInCurentChunk = ChunkCreator.SIZEOF_CHUNK_HEADER;
      }
      if (action == MemStoreCompactionStrategy.Action.COMPACT && !alreadyCopied) {

        // For compaction copy cell to the new segment (MSLAB copy),here we set forceCloneOfBigCell
        // to true, because the chunk which the cell is allocated may be freed after the compaction
        // is completed, see HBASE-27464.
        c = maybeCloneWithAllocator(c, true);
      }
      offsetInCurentChunk = // add the Cell reference to the index chunk
        createCellReference((ByteBufferKeyValue) c, chunks[currentChunkIdx].getData(),
          offsetInCurentChunk);
      // the sizes still need to be updated in the new segment
      // second parameter true, because in compaction/merge the addition of the cell to new segment
      // is always successful
      updateMetaInfo(c, true, null); // updates the size per cell
      if (action == MemStoreCompactionStrategy.Action.MERGE_COUNT_UNIQUE_KEYS) {
        // counting number of unique keys
        if (prev != null) {
          if (!CellUtil.matchingRowColumnBytes(prev, c)) {
            numUniqueKeys++;
          }
        } else {
          numUniqueKeys++;
        }
      }
      prev = c;
    }
    if (action == MemStoreCompactionStrategy.Action.COMPACT) {
      numUniqueKeys = numOfCells;
    } else if (action != MemStoreCompactionStrategy.Action.MERGE_COUNT_UNIQUE_KEYS) {
      numUniqueKeys = CellSet.UNKNOWN_NUM_UNIQUES;
    }
    // build the immutable CellSet
    CellChunkMap<ExtendedCell> ccm =
      new CellChunkMap<>(getComparator(), chunks, 0, numOfCellsAfterCompaction, false);
    this.setCellSet(null, new CellSet<>(ccm, numUniqueKeys)); // update the CellSet of this Segment
  }
------------------------------------------------------------------------ C-tor to be used when
new CellChunkImmutableSegment is built as a result of flattening of CSLMImmutableSegment The
given iterator returns the Cells that "survived" the compaction.
hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellChunkImmutableSegment.java