List<InputSplit> roundRobin(List<InputSplit> inputs) throws IOException {
    if ((inputs == null) || inputs.isEmpty()) {
      return inputs;
    }
    List<InputSplit> result = new ArrayList<>(inputs.size());
    // Prepare a hashmap with each region server as key and list of Input Splits as value
    Map<String, List<InputSplit>> regionServerSplits = new HashMap<>();
    for (InputSplit is : inputs) {
      if (is instanceof TableSplit) {
        String regionServer = ((TableSplit) is).getRegionLocation();
        if (regionServer != null && !StringUtils.isBlank(regionServer)) {
          regionServerSplits.computeIfAbsent(regionServer, k -> new ArrayList<>()).add(is);
          continue;
        }
      }
      // If TableSplit or region server not found, add it anyways.
      result.add(is);
    }
    // Write out splits in a manner that spreads splits for a RegionServer to avoid 'clumping'.
    while (!regionServerSplits.isEmpty()) {
      Iterator<List<InputSplit>> iter = regionServerSplits.values().iterator();
      while (iter.hasNext()) {
        List<InputSplit> inputSplitListForRegion = iter.next();
        if (!inputSplitListForRegion.isEmpty()) {
          result.add(inputSplitListForRegion.remove(0));
        }
        if (inputSplitListForRegion.isEmpty()) {
          iter.remove();
        }
      }
    }
    return result;
  }
Spread the splits list so as to avoid clumping on RegionServers. Order splits so every server
gets one split before a server gets a second, and so on; i.e. round-robin the splits amongst
the servers in the cluster.
hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/RoundRobinTableInputFormat.java