code: public List<Bucket> getHistogram(List<Long> bucketUpperBounds, MiddleFunction middleFunction)
      {
          checkArgument(Ordering.natural().isOrdered(bucketUpperBounds), "buckets must be sorted in increasing order");
  
          ImmutableList.Builder<Bucket> builder = ImmutableList.builder();
          PeekingIterator<Long> iterator = Iterators.peekingIterator(bucketUpperBounds.iterator());
  
          HistogramBuilderStateHolder holder = new HistogramBuilderStateHolder();
  
          double normalizationFactor = weight(TimeUnit.NANOSECONDS.toSeconds(ticker.read()));
  
          postOrderTraversal(root, node -> {
              while (iterator.hasNext() && iterator.peek() <= upperBound(node)) {
                  double bucketCount = holder.sum - holder.lastSum;
  
                  Bucket bucket = new Bucket(bucketCount / normalizationFactor, holder.bucketWeightedSum / bucketCount);
  
                  builder.add(bucket);
                  holder.lastSum = holder.sum;
                  holder.bucketWeightedSum = 0;
                  iterator.next();
              }
  
              holder.bucketWeightedSum += middleFunction.middle(lowerBound(node), upperBound(node)) * counts[node];
              holder.sum += counts[node];
              return iterator.hasNext();
          });
  
          while (iterator.hasNext()) {
              double bucketCount = holder.sum - holder.lastSum;
              Bucket bucket = new Bucket(bucketCount / normalizationFactor, holder.bucketWeightedSum / bucketCount);
  
              builder.add(bucket);
  
              iterator.next();
          }
  
          return builder.build();
      }
docs: is calculated.