class HotspotIntegerGenerator extends NumberGenerator {

  private final long lowerBound;
  private final long upperBound;
  private final long hotInterval;
  private final long coldInterval;
  private final double hotsetFraction;
  private final double hotOpnFraction;

  /**
   * Create a generator for Hotspot distributions.
   *
   * @param lowerBound lower bound of the distribution.
   * @param upperBound upper bound of the distribution.
   * @param hotsetFraction percentage of data item
   * @param hotOpnFraction percentage of operations accessing the hot set.
   */
  public HotspotIntegerGenerator(long lowerBound, long upperBound,
                                 double hotsetFraction, double hotOpnFraction) {
    if (hotsetFraction < 0.0 || hotsetFraction > 1.0) {
      System.err.println("Hotset fraction out of range. Setting to 0.0");
      hotsetFraction = 0.0;
    }
    if (hotOpnFraction < 0.0 || hotOpnFraction > 1.0) {
      System.err.println("Hot operation fraction out of range. Setting to 0.0");
      hotOpnFraction = 0.0;
    }
    if (lowerBound > upperBound) {
      System.err.println("Upper bound of Hotspot generator smaller than the lower bound. " +
          "Swapping the values.");
      long temp = lowerBound;
      lowerBound = upperBound;
      upperBound = temp;
    }
    this.lowerBound = lowerBound;
    this.upperBound = upperBound;
    this.hotsetFraction = hotsetFraction;
    long interval = upperBound - lowerBound + 1;
    this.hotInterval = (int) (interval * hotsetFraction);
    this.coldInterval = interval - hotInterval;
    this.hotOpnFraction = hotOpnFraction;
  }

  @Override
  public Long nextValue() {<FILL_FUNCTION_BODY>}

  /**
   * @return the lowerBound
   */
  public long getLowerBound() {
    return lowerBound;
  }

  /**
   * @return the upperBound
   */
  public long getUpperBound() {
    return upperBound;
  }

  /**
   * @return the hotsetFraction
   */
  public double getHotsetFraction() {
    return hotsetFraction;
  }

  /**
   * @return the hotOpnFraction
   */
  public double getHotOpnFraction() {
    return hotOpnFraction;
  }

  @Override
  public double mean() {
    return hotOpnFraction * (lowerBound + hotInterval / 2.0)
        + (1 - hotOpnFraction) * (lowerBound + hotInterval + coldInterval / 2.0);
  }
}

    long value = 0;
    Random random = ThreadLocalRandom.current();
    if (random.nextDouble() < hotOpnFraction) {
      // Choose a value from the hot set.
      value = lowerBound + Math.abs(random.nextLong()) % hotInterval;
    } else {
      // Choose a value from the cold set.
      value = lowerBound + hotInterval + Math.abs(random.nextLong()) % coldInterval;
    }
    setLastValue(value);
    return value;
  
<methods>public non-sealed void <init>() ,public java.lang.Number lastValue() ,public abstract double mean() <variables>private java.lang.Number lastVal