void selectPartitions(Pair<byte[][], byte[][]> regionStartEndKeys) {
      List<byte[]> startKeys = new ArrayList<>();
      for (int i = 0; i < regionStartEndKeys.getFirst().length; i++) {
        byte[] regionStartKey = regionStartEndKeys.getFirst()[i];
        byte[] regionEndKey = regionStartEndKeys.getSecond()[i];

        // if scan begins after this region, or starts before this region, then drop this region
        // in other words:
        // IF (scan begins before the end of this region
        // AND scan ends before the start of this region)
        // THEN include this region
        if (
          (isTableStartRow(startRow) || isTableEndRow(regionEndKey)
            || Bytes.compareTo(startRow, regionEndKey) < 0)
            && (isTableEndRow(stopRow) || isTableStartRow(regionStartKey)
              || Bytes.compareTo(stopRow, regionStartKey) > 0)
        ) {
          startKeys.add(regionStartKey);
        }
      }

      int numRegions = startKeys.size();
      if (numHashFiles == 0) {
        numHashFiles = numRegions / 100;
      }
      if (numHashFiles == 0) {
        numHashFiles = 1;
      }
      if (numHashFiles > numRegions) {
        // can't partition within regions
        numHashFiles = numRegions;
      }

      // choose a subset of start keys to group regions into ranges
      partitions = new ArrayList<>(numHashFiles - 1);
      // skip the first start key as it is not a partition between ranges.
      for (long i = 1; i < numHashFiles; i++) {
        int splitIndex = (int) (numRegions * i / numHashFiles);
        partitions.add(new ImmutableBytesWritable(startKeys.get(splitIndex)));
      }
    }
Choose partitions between row ranges to hash to a single output file Selects region
boundaries that fall within the scan range, and groups them into the desired number of
partitions.
hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/HashTable.java