@@ -34,6 +34,8 @@ public class Sketch {
3434 int size ;
3535 int head ;
3636
37+ private double [] values = new double [0 ];
38+
3739 double min ;
3840 double max ;
3941 double sum ;
@@ -110,40 +112,66 @@ public long count() {
110112 }
111113
112114 /**
113- * Builds the sketch from the given values. The {@code values} array is modified in place
114- * (sorted); callers that need to preserve the original ordering should pass a copy.
115+ * Builds the sketch from the given values.
115116 *
116- * @param values the observations to include in the sketch; sorted in place
117- * @param sampleRate the sampling rate used to collect {@code values }, in {@code (0, 1]}. Each
118- * observation is weighted by {@code 1 / sampleRate} when accumulating counts and sums.
117+ * @param observations the observations to include in the sketch
118+ * @param sampleRate the sampling rate used to collect {@code observations }, in {@code (0, 1]}.
119+ * Each observation is weighted by {@code 1 / sampleRate} when accumulating counts and sums.
119120 * Rates below ~1.08e-19 saturate the per-observation weight; bin counts and the total
120121 * {@code count} field saturate at {@link Long#MAX_VALUE} on overflow.
121122 */
122- public void build (long [] values , double sampleRate ) {
123- if (Double .isNaN (sampleRate ) || sampleRate <= 0 || sampleRate > 1 ) {
124- throw new IllegalArgumentException ("sampleRate is out of range" );
123+ public void build (long [] observations , double sampleRate ) {
124+ validateSampleRate (sampleRate );
125+ reset ();
126+ if (observations == null || observations .length == 0 ) {
127+ return ;
128+ }
129+ ensureCapacity (observations .length );
130+ for (int i = 0 ; i < observations .length ; i ++) {
131+ values [i ] = observations [i ];
125132 }
133+ buildInner (observations .length , sampleRate );
134+ }
126135
136+ /**
137+ * Builds the sketch from the given values.
138+ *
139+ * @param observations the observations to include in the sketch
140+ * @param sampleRate the sampling rate used to collect {@code observations}, in {@code (0, 1]}.
141+ * Each observation is weighted by {@code 1 / sampleRate} when accumulating counts and sums.
142+ * Rates below ~1.08e-19 saturate the per-observation weight; bin counts and the total
143+ * {@code count} field saturate at {@link Long#MAX_VALUE} on overflow.
144+ */
145+ public void build (double [] observations , double sampleRate ) {
146+ validateSampleRate (sampleRate );
127147 reset ();
128- buildInner (values , sampleRate );
148+ if (observations == null || observations .length == 0 ) {
149+ return ;
150+ }
151+ ensureCapacity (observations .length );
152+ System .arraycopy (observations , 0 , values , 0 , observations .length );
153+ buildInner (observations .length , sampleRate );
129154 }
130155
131- private void buildInner ( final long [] values , double sampleRate ) {
132- if (values == null || values . length == 0 ) {
133- return ;
156+ private static void validateSampleRate ( double sampleRate ) {
157+ if (Double . isNaN ( sampleRate ) || sampleRate <= 0 || sampleRate > 1 ) {
158+ throw new IllegalArgumentException ( "sampleRate is out of range" ) ;
134159 }
160+ }
135161
136- Arrays .sort (values );
162+ private void buildInner (int length , double sampleRate ) {
163+ Arrays .sort (values , 0 , length );
137164
138165 final long sampleSize = (long ) (1 / sampleRate );
139166 min = values [0 ];
140- max = values [values . length - 1 ];
141- count = satMul (sampleSize , values . length );
167+ max = values [length - 1 ];
168+ count = satMul (sampleSize , length );
142169
143170 short topKey = negInfKey - 1 ;
144171 long topCount = 0 ;
145172
146- for (long val : values ) {
173+ for (int i = 0 ; i < length ; i ++) {
174+ double val = values [i ];
147175 sum += val / sampleRate ;
148176
149177 short key = key (val );
@@ -162,6 +190,12 @@ private void buildInner(final long[] values, double sampleRate) {
162190 append (topKey , topCount );
163191 }
164192
193+ private void ensureCapacity (int needed ) {
194+ if (values .length < needed ) {
195+ values = new double [needed ];
196+ }
197+ }
198+
165199 private void reset () {
166200 min = 0 ;
167201 max = 0 ;
0 commit comments