2828import  java .util .OptionalLong ;
2929
3030/** 
31-  * Base class  for implementations of exponential histograms adhering to the 
31+  * Interface  for implementations of exponential histograms adhering to the 
3232 * <a href="https://opentelemetry.io/docs/specs/otel/metrics/data-model/#exponentialhistogram">OpenTelemetry definition</a>. 
33-  * This class  supports sparse implementations, allowing iteration over buckets without requiring direct index access.<br> 
33+  * This interface  supports sparse implementations, allowing iteration over buckets without requiring direct index access.<br> 
3434 * The most important properties are: 
3535 * <ul> 
3636 *     <li>The histogram has a scale parameter, which defines the accuracy. A higher scale implies a higher accuracy. 
4545 * Additionally, all algorithms assume that samples within a bucket are located at a single point: the point of least relative error 
4646 * (see {@link ExponentialScaleUtils#getPointOfLeastRelativeError(long, int)}). 
4747 */ 
48- public  abstract   class   ExponentialHistogram  implements  Accountable  {
48+ public  interface   ExponentialHistogram  extends  Accountable  {
4949
5050    // TODO(b/128622): support min/max storage and merging. 
5151    // TODO(b/128622): Add special positive and negative infinity buckets 
@@ -56,42 +56,42 @@ public abstract class ExponentialHistogram implements Accountable {
5656    // Theoretically, a MAX_SCALE of 51 would work and would still cover the entire range of double values. 
5757    // For that to work, the math for converting from double to indices and back would need to be reworked. 
5858    // One option would be to use "Quadruple": https://github.com/m-vokhm/Quadruple 
59-     public   static   final   int  MAX_SCALE  = 38 ;
59+     int  MAX_SCALE  = 38 ;
6060
6161    // At this scale, all double values fall into a single bucket. 
62-     public   static   final   int  MIN_SCALE  = -11 ;
62+     int  MIN_SCALE  = -11 ;
6363
6464    // Only use 62 bits (plus the sign bit) at max to allow computing the difference between the smallest and largest index without causing 
6565    // an overflow. 
6666    // The extra bit also provides room for compact storage tricks. 
67-     public   static   final   int  MAX_INDEX_BITS  = 62 ;
68-     public   static   final   long  MAX_INDEX  = (1L  << MAX_INDEX_BITS ) - 1 ;
69-     public   static   final   long  MIN_INDEX  = -MAX_INDEX ;
67+     int  MAX_INDEX_BITS  = 62 ;
68+     long  MAX_INDEX  = (1L  << MAX_INDEX_BITS ) - 1 ;
69+     long  MIN_INDEX  = -MAX_INDEX ;
7070
7171    /** 
7272     * The scale of the histogram. Higher scales result in higher accuracy but potentially more buckets. 
7373     * Must be less than or equal to {@link #MAX_SCALE} and greater than or equal to {@link #MIN_SCALE}. 
7474     * 
7575     * @return the scale of the histogram 
7676     */ 
77-     public   abstract   int  scale ();
77+     int  scale ();
7878
7979    /** 
8080     * @return the {@link ZeroBucket} representing the number of zero (or close-to-zero) values and its threshold 
8181     */ 
82-     public   abstract   ZeroBucket  zeroBucket ();
82+     ZeroBucket  zeroBucket ();
8383
8484    /** 
8585     * @return a {@link Buckets} instance for the populated buckets covering the positive value range of this histogram. 
8686     * The {@link BucketIterator#scale()} of iterators obtained via {@link Buckets#iterator()} must be the same as {@link #scale()}. 
8787     */ 
88-     public   abstract   Buckets  positiveBuckets ();
88+     Buckets  positiveBuckets ();
8989
9090    /** 
9191     * @return a {@link Buckets} instance for the populated buckets covering the negative value range of this histogram. 
9292     * The {@link BucketIterator#scale()} of iterators obtained via {@link Buckets#iterator()} must be the same as {@link #scale()}. 
9393     */ 
94-     public   abstract   Buckets  negativeBuckets ();
94+     Buckets  negativeBuckets ();
9595
9696    /** 
9797     * Returns the sum of all values represented by this histogram. 
@@ -100,22 +100,20 @@ public abstract class ExponentialHistogram implements Accountable {
100100     * 
101101     * @return the sum, guaranteed to be zero for empty histograms 
102102     */ 
103-     public   abstract   double  sum ();
103+     double  sum ();
104104
105105    /** 
106106     * Returns the number of values represented by this histogram. 
107107     * In other words, this is the sum of the counts of all buckets including the zero bucket. 
108108     * 
109109     * @return the value count, guaranteed to be zero for empty histograms 
110110     */ 
111-     public  long  valueCount () {
112-         return  zeroBucket ().count () + positiveBuckets ().valueCount () + negativeBuckets ().valueCount ();
113-     }
111+     long  valueCount ();
114112
115113    /** 
116114     * Represents a bucket range of an {@link ExponentialHistogram}, either the positive or the negative range. 
117115     */ 
118-     public   interface  Buckets  {
116+     interface  Buckets  {
119117
120118        /** 
121119         * @return a {@link BucketIterator} for the populated buckets of this bucket range. 
@@ -135,23 +133,22 @@ public interface Buckets {
135133
136134    }
137135
138-     @ Override 
139-     public  boolean  equals (Object  other ) {
140-         if  (this  == other ) return  true ;
141-         if  (other  == null ) return  false ;
142- 
143-         if  ((other  instanceof  ExponentialHistogram ) == false ) {
144-             return  false ;
145-         }
146-         ExponentialHistogram  that  = (ExponentialHistogram ) other ;
147- 
148-         if  (scale () != that .scale ()) return  false ;
149-         if  (sum () != that .sum ()) return  false ;
150-         if  (zeroBucket ().equals (that .zeroBucket ()) == false ) return  false ;
151-         if  (bucketIteratorsEqual (negativeBuckets ().iterator (), that .negativeBuckets ().iterator ()) == false ) return  false ;
152-         if  (bucketIteratorsEqual (positiveBuckets ().iterator (), that .positiveBuckets ().iterator ()) == false ) return  false ;
153- 
154-         return  true ;
136+     /** 
137+      * Value-based equality for exponential histograms. 
138+      * @param a the first histogram (can be null) 
139+      * @param b the second histogram (can be null) 
140+      * @return true, if both histograms are equal 
141+      */ 
142+     static  boolean  equals (ExponentialHistogram  a , ExponentialHistogram  b ) {
143+         if  (a  == b ) return  true ;
144+         if  (a  == null ) return  false ;
145+         if  (b  == null ) return  false ;
146+ 
147+         return  a .scale () == b .scale ()
148+             && a .sum () == b .sum ()
149+             && a .zeroBucket ().equals (b .zeroBucket ())
150+             && bucketIteratorsEqual (a .negativeBuckets ().iterator (), b .negativeBuckets ().iterator ())
151+             && bucketIteratorsEqual (a .positiveBuckets ().iterator (), b .positiveBuckets ().iterator ());
155152    }
156153
157154    private  static  boolean  bucketIteratorsEqual (BucketIterator  a , BucketIterator  b ) {
@@ -168,19 +165,23 @@ private static boolean bucketIteratorsEqual(BucketIterator a, BucketIterator b)
168165        return  a .hasNext () == b .hasNext ();
169166    }
170167
171-     @ Override 
172-     public  int  hashCode () {
173-         int  hash  = scale ();
174-         hash  = 31  * hash  + Double .hashCode (sum ());
175-         hash  = 31  * hash  + zeroBucket ().hashCode ();
176-         hash  = 31  * hash  + Long .hashCode (valueCount ());
168+     /** 
169+      * Default hash code implementation to be used with {@link #equals(ExponentialHistogram, ExponentialHistogram)}. 
170+      * @param histogram the histogram to hash 
171+      * @return the hash code 
172+      */ 
173+     static  int  hashCode (ExponentialHistogram  histogram ) {
174+         int  hash  = histogram .scale ();
175+         hash  = 31  * hash  + Double .hashCode (histogram .sum ());
176+         hash  = 31  * hash  + histogram .zeroBucket ().hashCode ();
177+         hash  = 31  * hash  + Long .hashCode (histogram .valueCount ());
177178        // we intentionally don't include the hash of the buckets here, because that is likely expensive to compute 
178179        // instead, we assume that the value count and sum are a good enough approximation in most cases to minimize collisions 
179180        // the value count is typically available as a cached value and doesn't involve iterating over all buckets 
180181        return  hash ;
181182    }
182183
183-     public   static  ExponentialHistogram  empty () {
184+     static  ExponentialHistogram  empty () {
184185        return  EmptyExponentialHistogram .INSTANCE ;
185186    }
186187
@@ -194,7 +195,7 @@ public static ExponentialHistogram empty() {
194195     * @param values the values to be added to the histogram 
195196     * @return a new {@link ReleasableExponentialHistogram} 
196197     */ 
197-     public   static  ReleasableExponentialHistogram  create (int  maxBucketCount , ExponentialHistogramCircuitBreaker  breaker , double ... values ) {
198+     static  ReleasableExponentialHistogram  create (int  maxBucketCount , ExponentialHistogramCircuitBreaker  breaker , double ... values ) {
198199        try  (ExponentialHistogramGenerator  generator  = ExponentialHistogramGenerator .create (maxBucketCount , breaker )) {
199200            for  (double  val  : values ) {
200201                generator .add (val );
@@ -211,7 +212,7 @@ public static ReleasableExponentialHistogram create(int maxBucketCount, Exponent
211212     * @param histograms the histograms to merge 
212213     * @return the merged histogram 
213214     */ 
214-     public   static  ReleasableExponentialHistogram  merge (
215+     static  ReleasableExponentialHistogram  merge (
215216        int  maxBucketCount ,
216217        ExponentialHistogramCircuitBreaker  breaker ,
217218        Iterator <ExponentialHistogram > histograms 
@@ -232,7 +233,7 @@ public static ReleasableExponentialHistogram merge(
232233     * @param histograms the histograms to merge 
233234     * @return the merged histogram 
234235     */ 
235-     public   static  ReleasableExponentialHistogram  merge (
236+     static  ReleasableExponentialHistogram  merge (
236237        int  maxBucketCount ,
237238        ExponentialHistogramCircuitBreaker  breaker ,
238239        ExponentialHistogram ... histograms 
0 commit comments