public void print(boolean isDetailMode) {
    if (!isFilledUp) {
      System.err.println("[Error] Region assignment verification report" + "hasn't been filled up");
    }
    DecimalFormat df = new java.text.DecimalFormat("#.##");

    // Print some basic information
    System.out.println("Region Assignment Verification for Table: " + tableName
      + "\n\tTotal regions : " + totalRegions);

    // Print the number of regions on each kinds of the favored nodes
    System.out.println("\tTotal regions on favored nodes " + totalFavoredAssignments);
    for (FavoredNodesPlan.Position p : FavoredNodesPlan.Position.values()) {
      System.out.println(
        "\t\tTotal regions on " + p.toString() + " region servers: " + favoredNodes[p.ordinal()]);
    }
    // Print the number of regions in each kinds of invalid assignment
    System.out.println("\tTotal unassigned regions: " + unAssignedRegionsList.size());
    if (isDetailMode) {
      for (RegionInfo region : unAssignedRegionsList) {
        System.out.println("\t\t" + region.getRegionNameAsString());
      }
    }

    System.out
      .println("\tTotal regions NOT on favored nodes: " + nonFavoredAssignedRegionList.size());
    if (isDetailMode) {
      for (RegionInfo region : nonFavoredAssignedRegionList) {
        System.out.println("\t\t" + region.getRegionNameAsString());
      }
    }

    System.out
      .println("\tTotal regions without favored nodes: " + regionsWithoutValidFavoredNodes.size());
    if (isDetailMode) {
      for (RegionInfo region : regionsWithoutValidFavoredNodes) {
        System.out.println("\t\t" + region.getRegionNameAsString());
      }
    }

    // Print the locality information if enabled
    if (this.enforceLocality && totalRegions != 0) {
      // Print the actual locality for this table
      float actualLocality = 100 * this.actualLocalitySummary / (float) totalRegions;
      System.out.println("\n\tThe actual avg locality is " + df.format(actualLocality) + " %");

      // Print the expected locality if regions are placed on the each kinds of
      // favored nodes
      for (FavoredNodesPlan.Position p : FavoredNodesPlan.Position.values()) {
        float avgLocality = 100 * (favoredNodesLocalitySummary[p.ordinal()] / (float) totalRegions);
        System.out.println("\t\tThe expected avg locality if all regions" + " on the "
          + p.toString() + " region servers: " + df.format(avgLocality) + " %");
      }
    }

    // Print the region balancing information
    System.out.println("\n\tTotal hosting region servers: " + totalRegionServers);
    // Print the region balance information
    if (totalRegionServers != 0) {
      System.out.println("\tAvg dispersion num: " + df.format(avgDispersionNum)
        + " hosts;\tMax dispersion num: " + df.format(maxDispersionNum)
        + " hosts;\tMin dispersion num: " + df.format(minDispersionNum) + " hosts;");

      System.out.println("\t\tThe number of the region servers with the max" + " dispersion num: "
        + this.maxDispersionNumServerSet.size());
      if (isDetailMode) {
        printHServerAddressSet(maxDispersionNumServerSet);
      }

      System.out.println("\t\tThe number of the region servers with the min" + " dispersion num: "
        + this.minDispersionNumServerSet.size());
      if (isDetailMode) {
        printHServerAddressSet(maxDispersionNumServerSet);
      }

      System.out.println("\tAvg dispersion score: " + df.format(avgDispersionScore)
        + ";\tMax dispersion score: " + df.format(maxDispersionScore) + ";\tMin dispersion score: "
        + df.format(minDispersionScore) + ";");

      System.out.println("\t\tThe number of the region servers with the max" + " dispersion score: "
        + this.maxDispersionScoreServerSet.size());
      if (isDetailMode) {
        printHServerAddressSet(maxDispersionScoreServerSet);
      }

      System.out.println("\t\tThe number of the region servers with the min" + " dispersion score: "
        + this.minDispersionScoreServerSet.size());
      if (isDetailMode) {
        printHServerAddressSet(minDispersionScoreServerSet);
      }

      System.out.println("\tAvg regions/region server: " + df.format(avgRegionsOnRS)
        + ";\tMax regions/region server: " + maxRegionsOnRS + ";\tMin regions/region server: "
        + minRegionsOnRS + ";");

      // Print the details about the most loaded region servers
      System.out
        .println("\t\tThe number of the most loaded region servers: " + mostLoadedRSSet.size());
      if (isDetailMode) {
        printHServerAddressSet(mostLoadedRSSet);
      }

      // Print the details about the least loaded region servers
      System.out
        .println("\t\tThe number of the least loaded region servers: " + leastLoadedRSSet.size());
      if (isDetailMode) {
        printHServerAddressSet(leastLoadedRSSet);
      }
    }
    System.out.println("==============================");
  }
Return a list which contains 3 elements: average dispersion score, max dispersion score and min
dispersion score as first, second and third elements, respectively.
hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/AssignmentVerificationReport.java