001/* 002 * Copyright (C) 2012 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014 015package com.google.common.math; 016 017import static com.google.common.base.Preconditions.checkArgument; 018import static com.google.common.base.Preconditions.checkNotNull; 019import static com.google.common.base.Preconditions.checkState; 020import static com.google.common.math.DoubleUtils.ensureNonNegative; 021import static com.google.common.math.StatsAccumulator.calculateNewMeanNonFinite; 022import static com.google.common.primitives.Doubles.isFinite; 023import static java.lang.Double.NaN; 024import static java.lang.Double.doubleToLongBits; 025import static java.lang.Double.isNaN; 026 027import com.google.common.annotations.GwtIncompatible; 028import com.google.common.annotations.J2ktIncompatible; 029import com.google.common.base.MoreObjects; 030import com.google.common.base.Objects; 031import java.io.Serializable; 032import java.nio.ByteBuffer; 033import java.nio.ByteOrder; 034import java.util.Iterator; 035import java.util.stream.Collector; 036import java.util.stream.DoubleStream; 037import java.util.stream.IntStream; 038import java.util.stream.LongStream; 039import org.checkerframework.checker.nullness.qual.Nullable; 040 041/** 042 * A bundle of statistical summary values -- sum, count, mean/average, min and max, and several 043 * forms of variance -- that were computed from a single set of zero or more floating-point values. 044 * 045 * <p>There are two ways to obtain a {@code Stats} instance: 046 * 047 * <ul> 048 * <li>If all the values you want to summarize are already known, use the appropriate {@code 049 * Stats.of} factory method below. Primitive arrays, iterables and iterators of any kind of 050 * {@code Number}, and primitive varargs are supported. 051 * <li>Or, to avoid storing up all the data first, create a {@link StatsAccumulator} instance, 052 * feed values to it as you get them, then call {@link StatsAccumulator#snapshot}. 053 * </ul> 054 * 055 * <p>Static convenience methods called {@code meanOf} are also provided for users who wish to 056 * calculate <i>only</i> the mean. 057 * 058 * <p><b>Java 8+ users:</b> If you are not using any of the variance statistics, you may wish to use 059 * built-in JDK libraries instead of this class. 060 * 061 * @author Pete Gillin 062 * @author Kevin Bourrillion 063 * @since 20.0 064 */ 065@J2ktIncompatible 066@GwtIncompatible 067public final class Stats implements Serializable { 068 069 private final long count; 070 private final double mean; 071 private final double sumOfSquaresOfDeltas; 072 private final double min; 073 private final double max; 074 075 /** 076 * Internal constructor. Users should use {@link #of} or {@link StatsAccumulator#snapshot}. 077 * 078 * <p>To ensure that the created instance obeys its contract, the parameters should satisfy the 079 * following constraints. This is the callers responsibility and is not enforced here. 080 * 081 * <ul> 082 * <li>If {@code count} is 0, {@code mean} may have any finite value (its only usage will be to 083 * get multiplied by 0 to calculate the sum), and the other parameters may have any values 084 * (they will not be used). 085 * <li>If {@code count} is 1, {@code sumOfSquaresOfDeltas} must be exactly 0.0 or {@link 086 * Double#NaN}. 087 * </ul> 088 */ 089 Stats(long count, double mean, double sumOfSquaresOfDeltas, double min, double max) { 090 this.count = count; 091 this.mean = mean; 092 this.sumOfSquaresOfDeltas = sumOfSquaresOfDeltas; 093 this.min = min; 094 this.max = max; 095 } 096 097 /** 098 * Returns statistics over a dataset containing the given values. 099 * 100 * @param values a series of values, which will be converted to {@code double} values (this may 101 * cause loss of precision) 102 */ 103 public static Stats of(Iterable<? extends Number> values) { 104 StatsAccumulator accumulator = new StatsAccumulator(); 105 accumulator.addAll(values); 106 return accumulator.snapshot(); 107 } 108 109 /** 110 * Returns statistics over a dataset containing the given values. The iterator will be completely 111 * consumed by this method. 112 * 113 * @param values a series of values, which will be converted to {@code double} values (this may 114 * cause loss of precision) 115 */ 116 public static Stats of(Iterator<? extends Number> values) { 117 StatsAccumulator accumulator = new StatsAccumulator(); 118 accumulator.addAll(values); 119 return accumulator.snapshot(); 120 } 121 122 /** 123 * Returns statistics over a dataset containing the given values. 124 * 125 * @param values a series of values 126 */ 127 public static Stats of(double... values) { 128 StatsAccumulator accumulator = new StatsAccumulator(); 129 accumulator.addAll(values); 130 return accumulator.snapshot(); 131 } 132 133 /** 134 * Returns statistics over a dataset containing the given values. 135 * 136 * @param values a series of values 137 */ 138 public static Stats of(int... values) { 139 StatsAccumulator accumulator = new StatsAccumulator(); 140 accumulator.addAll(values); 141 return accumulator.snapshot(); 142 } 143 144 /** 145 * Returns statistics over a dataset containing the given values. 146 * 147 * @param values a series of values, which will be converted to {@code double} values (this may 148 * cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15)) 149 */ 150 public static Stats of(long... values) { 151 StatsAccumulator accumulator = new StatsAccumulator(); 152 accumulator.addAll(values); 153 return accumulator.snapshot(); 154 } 155 156 /** 157 * Returns statistics over a dataset containing the given values. The stream will be completely 158 * consumed by this method. 159 * 160 * <p>If you have a {@code Stream<Double>} rather than a {@code DoubleStream}, you should collect 161 * the values using {@link #toStats()} instead. 162 * 163 * @param values a series of values 164 * @since 33.4.0 (but since 28.2 in the JRE flavor) 165 */ 166 @SuppressWarnings("Java7ApiChecker") 167 @IgnoreJRERequirement // Users will use this only if they're already using streams. 168 public static Stats of(DoubleStream values) { 169 return values 170 .collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll) 171 .snapshot(); 172 } 173 174 /** 175 * Returns statistics over a dataset containing the given values. The stream will be completely 176 * consumed by this method. 177 * 178 * <p>If you have a {@code Stream<Integer>} rather than an {@code IntStream}, you should collect 179 * the values using {@link #toStats()} instead. 180 * 181 * @param values a series of values 182 * @since 33.4.0 (but since 28.2 in the JRE flavor) 183 */ 184 @SuppressWarnings("Java7ApiChecker") 185 @IgnoreJRERequirement // Users will use this only if they're already using streams. 186 public static Stats of(IntStream values) { 187 return values 188 .collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll) 189 .snapshot(); 190 } 191 192 /** 193 * Returns statistics over a dataset containing the given values. The stream will be completely 194 * consumed by this method. 195 * 196 * <p>If you have a {@code Stream<Long>} rather than a {@code LongStream}, you should collect the 197 * values using {@link #toStats()} instead. 198 * 199 * @param values a series of values, which will be converted to {@code double} values (this may 200 * cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15)) 201 * @since 33.4.0 (but since 28.2 in the JRE flavor) 202 */ 203 @SuppressWarnings("Java7ApiChecker") 204 @IgnoreJRERequirement // Users will use this only if they're already using streams. 205 public static Stats of(LongStream values) { 206 return values 207 .collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll) 208 .snapshot(); 209 } 210 211 /** 212 * Returns a {@link Collector} which accumulates statistics from a {@link java.util.stream.Stream} 213 * of any type of boxed {@link Number} into a {@link Stats}. Use by calling {@code 214 * boxedNumericStream.collect(toStats())}. The numbers will be converted to {@code double} values 215 * (which may cause loss of precision). 216 * 217 * <p>If you have any of the primitive streams {@code DoubleStream}, {@code IntStream}, or {@code 218 * LongStream}, you should use the factory method {@link #of} instead. 219 * 220 * @since 33.4.0 (but since 28.2 in the JRE flavor) 221 */ 222 @SuppressWarnings("Java7ApiChecker") 223 @IgnoreJRERequirement // Users will use this only if they're already using streams. 224 public static Collector<Number, StatsAccumulator, Stats> toStats() { 225 return Collector.of( 226 StatsAccumulator::new, 227 (a, x) -> a.add(x.doubleValue()), 228 (l, r) -> { 229 l.addAll(r); 230 return l; 231 }, 232 StatsAccumulator::snapshot, 233 Collector.Characteristics.UNORDERED); 234 } 235 236 /** Returns the number of values. */ 237 public long count() { 238 return count; 239 } 240 241 /** 242 * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the 243 * values. The count must be non-zero. 244 * 245 * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of 246 * the arithmetic mean of the population. 247 * 248 * <h3>Non-finite values</h3> 249 * 250 * <p>If the dataset contains {@link Double#NaN} then the result is {@link Double#NaN}. If it 251 * contains both {@link Double#POSITIVE_INFINITY} and {@link Double#NEGATIVE_INFINITY} then the 252 * result is {@link Double#NaN}. If it contains {@link Double#POSITIVE_INFINITY} and finite values 253 * only or {@link Double#POSITIVE_INFINITY} only, the result is {@link Double#POSITIVE_INFINITY}. 254 * If it contains {@link Double#NEGATIVE_INFINITY} and finite values only or {@link 255 * Double#NEGATIVE_INFINITY} only, the result is {@link Double#NEGATIVE_INFINITY}. 256 * 257 * <p>If you only want to calculate the mean, use {@link #meanOf} instead of creating a {@link 258 * Stats} instance. 259 * 260 * @throws IllegalStateException if the dataset is empty 261 */ 262 public double mean() { 263 checkState(count != 0); 264 return mean; 265 } 266 267 /** 268 * Returns the sum of the values. 269 * 270 * <h3>Non-finite values</h3> 271 * 272 * <p>If the dataset contains {@link Double#NaN} then the result is {@link Double#NaN}. If it 273 * contains both {@link Double#POSITIVE_INFINITY} and {@link Double#NEGATIVE_INFINITY} then the 274 * result is {@link Double#NaN}. If it contains {@link Double#POSITIVE_INFINITY} and finite values 275 * only or {@link Double#POSITIVE_INFINITY} only, the result is {@link Double#POSITIVE_INFINITY}. 276 * If it contains {@link Double#NEGATIVE_INFINITY} and finite values only or {@link 277 * Double#NEGATIVE_INFINITY} only, the result is {@link Double#NEGATIVE_INFINITY}. 278 */ 279 public double sum() { 280 return mean * count; 281 } 282 283 /** 284 * Returns the <a href="http://en.wikipedia.org/wiki/Variance#Population_variance">population 285 * variance</a> of the values. The count must be non-zero. 286 * 287 * <p>This is guaranteed to return zero if the dataset contains only exactly one finite value. It 288 * is not guaranteed to return zero when the dataset consists of the same value multiple times, 289 * due to numerical errors. However, it is guaranteed never to return a negative result. 290 * 291 * <h3>Non-finite values</h3> 292 * 293 * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link 294 * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}. 295 * 296 * @throws IllegalStateException if the dataset is empty 297 */ 298 public double populationVariance() { 299 checkState(count > 0); 300 if (isNaN(sumOfSquaresOfDeltas)) { 301 return NaN; 302 } 303 if (count == 1) { 304 return 0.0; 305 } 306 return ensureNonNegative(sumOfSquaresOfDeltas) / count(); 307 } 308 309 /** 310 * Returns the <a 311 * href="http://en.wikipedia.org/wiki/Standard_deviation#Definition_of_population_values"> 312 * population standard deviation</a> of the values. The count must be non-zero. 313 * 314 * <p>This is guaranteed to return zero if the dataset contains only exactly one finite value. It 315 * is not guaranteed to return zero when the dataset consists of the same value multiple times, 316 * due to numerical errors. However, it is guaranteed never to return a negative result. 317 * 318 * <h3>Non-finite values</h3> 319 * 320 * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link 321 * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}. 322 * 323 * @throws IllegalStateException if the dataset is empty 324 */ 325 public double populationStandardDeviation() { 326 return Math.sqrt(populationVariance()); 327 } 328 329 /** 330 * Returns the <a href="http://en.wikipedia.org/wiki/Variance#Sample_variance">unbiased sample 331 * variance</a> of the values. If this dataset is a sample drawn from a population, this is an 332 * unbiased estimator of the population variance of the population. The count must be greater than 333 * one. 334 * 335 * <p>This is not guaranteed to return zero when the dataset consists of the same value multiple 336 * times, due to numerical errors. However, it is guaranteed never to return a negative result. 337 * 338 * <h3>Non-finite values</h3> 339 * 340 * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link 341 * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}. 342 * 343 * @throws IllegalStateException if the dataset is empty or contains a single value 344 */ 345 public double sampleVariance() { 346 checkState(count > 1); 347 if (isNaN(sumOfSquaresOfDeltas)) { 348 return NaN; 349 } 350 return ensureNonNegative(sumOfSquaresOfDeltas) / (count - 1); 351 } 352 353 /** 354 * Returns the <a 355 * href="http://en.wikipedia.org/wiki/Standard_deviation#Corrected_sample_standard_deviation"> 356 * corrected sample standard deviation</a> of the values. If this dataset is a sample drawn from a 357 * population, this is an estimator of the population standard deviation of the population which 358 * is less biased than {@link #populationStandardDeviation()} (the unbiased estimator depends on 359 * the distribution). The count must be greater than one. 360 * 361 * <p>This is not guaranteed to return zero when the dataset consists of the same value multiple 362 * times, due to numerical errors. However, it is guaranteed never to return a negative result. 363 * 364 * <h3>Non-finite values</h3> 365 * 366 * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link 367 * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}. 368 * 369 * @throws IllegalStateException if the dataset is empty or contains a single value 370 */ 371 public double sampleStandardDeviation() { 372 return Math.sqrt(sampleVariance()); 373 } 374 375 /** 376 * Returns the lowest value in the dataset. The count must be non-zero. 377 * 378 * <h3>Non-finite values</h3> 379 * 380 * <p>If the dataset contains {@link Double#NaN} then the result is {@link Double#NaN}. If it 381 * contains {@link Double#NEGATIVE_INFINITY} and not {@link Double#NaN} then the result is {@link 382 * Double#NEGATIVE_INFINITY}. If it contains {@link Double#POSITIVE_INFINITY} and finite values 383 * only then the result is the lowest finite value. If it contains {@link 384 * Double#POSITIVE_INFINITY} only then the result is {@link Double#POSITIVE_INFINITY}. 385 * 386 * @throws IllegalStateException if the dataset is empty 387 */ 388 public double min() { 389 checkState(count != 0); 390 return min; 391 } 392 393 /** 394 * Returns the highest value in the dataset. The count must be non-zero. 395 * 396 * <h3>Non-finite values</h3> 397 * 398 * <p>If the dataset contains {@link Double#NaN} then the result is {@link Double#NaN}. If it 399 * contains {@link Double#POSITIVE_INFINITY} and not {@link Double#NaN} then the result is {@link 400 * Double#POSITIVE_INFINITY}. If it contains {@link Double#NEGATIVE_INFINITY} and finite values 401 * only then the result is the highest finite value. If it contains {@link 402 * Double#NEGATIVE_INFINITY} only then the result is {@link Double#NEGATIVE_INFINITY}. 403 * 404 * @throws IllegalStateException if the dataset is empty 405 */ 406 public double max() { 407 checkState(count != 0); 408 return max; 409 } 410 411 /** 412 * {@inheritDoc} 413 * 414 * <p><b>Note:</b> This tests exact equality of the calculated statistics, including the floating 415 * point values. Two instances are guaranteed to be considered equal if one is copied from the 416 * other using {@code second = new StatsAccumulator().addAll(first).snapshot()}, if both were 417 * obtained by calling {@code snapshot()} on the same {@link StatsAccumulator} without adding any 418 * values in between the two calls, or if one is obtained from the other after round-tripping 419 * through java serialization. However, floating point rounding errors mean that it may be false 420 * for some instances where the statistics are mathematically equal, including instances 421 * constructed from the same values in a different order... or (in the general case) even in the 422 * same order. (It is guaranteed to return true for instances constructed from the same values in 423 * the same order if {@code strictfp} is in effect, or if the system architecture guarantees 424 * {@code strictfp}-like semantics.) 425 */ 426 @Override 427 public boolean equals(@Nullable Object obj) { 428 if (obj == null) { 429 return false; 430 } 431 if (getClass() != obj.getClass()) { 432 return false; 433 } 434 Stats other = (Stats) obj; 435 return count == other.count 436 && doubleToLongBits(mean) == doubleToLongBits(other.mean) 437 && doubleToLongBits(sumOfSquaresOfDeltas) == doubleToLongBits(other.sumOfSquaresOfDeltas) 438 && doubleToLongBits(min) == doubleToLongBits(other.min) 439 && doubleToLongBits(max) == doubleToLongBits(other.max); 440 } 441 442 /** 443 * {@inheritDoc} 444 * 445 * <p><b>Note:</b> This hash code is consistent with exact equality of the calculated statistics, 446 * including the floating point values. See the note on {@link #equals} for details. 447 */ 448 @Override 449 public int hashCode() { 450 return Objects.hashCode(count, mean, sumOfSquaresOfDeltas, min, max); 451 } 452 453 @Override 454 public String toString() { 455 if (count() > 0) { 456 return MoreObjects.toStringHelper(this) 457 .add("count", count) 458 .add("mean", mean) 459 .add("populationStandardDeviation", populationStandardDeviation()) 460 .add("min", min) 461 .add("max", max) 462 .toString(); 463 } else { 464 return MoreObjects.toStringHelper(this).add("count", count).toString(); 465 } 466 } 467 468 double sumOfSquaresOfDeltas() { 469 return sumOfSquaresOfDeltas; 470 } 471 472 /** 473 * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the 474 * values. The count must be non-zero. 475 * 476 * <p>The definition of the mean is the same as {@link Stats#mean}. 477 * 478 * @param values a series of values, which will be converted to {@code double} values (this may 479 * cause loss of precision) 480 * @throws IllegalArgumentException if the dataset is empty 481 */ 482 public static double meanOf(Iterable<? extends Number> values) { 483 return meanOf(values.iterator()); 484 } 485 486 /** 487 * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the 488 * values. The count must be non-zero. 489 * 490 * <p>The definition of the mean is the same as {@link Stats#mean}. 491 * 492 * @param values a series of values, which will be converted to {@code double} values (this may 493 * cause loss of precision) 494 * @throws IllegalArgumentException if the dataset is empty 495 */ 496 public static double meanOf(Iterator<? extends Number> values) { 497 checkArgument(values.hasNext()); 498 long count = 1; 499 double mean = values.next().doubleValue(); 500 while (values.hasNext()) { 501 double value = values.next().doubleValue(); 502 count++; 503 if (isFinite(value) && isFinite(mean)) { 504 // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15) 505 mean += (value - mean) / count; 506 } else { 507 mean = calculateNewMeanNonFinite(mean, value); 508 } 509 } 510 return mean; 511 } 512 513 /** 514 * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the 515 * values. The count must be non-zero. 516 * 517 * <p>The definition of the mean is the same as {@link Stats#mean}. 518 * 519 * @param values a series of values 520 * @throws IllegalArgumentException if the dataset is empty 521 */ 522 public static double meanOf(double... values) { 523 checkArgument(values.length > 0); 524 double mean = values[0]; 525 for (int index = 1; index < values.length; index++) { 526 double value = values[index]; 527 if (isFinite(value) && isFinite(mean)) { 528 // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15) 529 mean += (value - mean) / (index + 1); 530 } else { 531 mean = calculateNewMeanNonFinite(mean, value); 532 } 533 } 534 return mean; 535 } 536 537 /** 538 * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the 539 * values. The count must be non-zero. 540 * 541 * <p>The definition of the mean is the same as {@link Stats#mean}. 542 * 543 * @param values a series of values 544 * @throws IllegalArgumentException if the dataset is empty 545 */ 546 public static double meanOf(int... values) { 547 checkArgument(values.length > 0); 548 double mean = values[0]; 549 for (int index = 1; index < values.length; index++) { 550 double value = values[index]; 551 if (isFinite(value) && isFinite(mean)) { 552 // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15) 553 mean += (value - mean) / (index + 1); 554 } else { 555 mean = calculateNewMeanNonFinite(mean, value); 556 } 557 } 558 return mean; 559 } 560 561 /** 562 * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the 563 * values. The count must be non-zero. 564 * 565 * <p>The definition of the mean is the same as {@link Stats#mean}. 566 * 567 * @param values a series of values, which will be converted to {@code double} values (this may 568 * cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15)) 569 * @throws IllegalArgumentException if the dataset is empty 570 */ 571 public static double meanOf(long... values) { 572 checkArgument(values.length > 0); 573 double mean = values[0]; 574 for (int index = 1; index < values.length; index++) { 575 double value = values[index]; 576 if (isFinite(value) && isFinite(mean)) { 577 // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15) 578 mean += (value - mean) / (index + 1); 579 } else { 580 mean = calculateNewMeanNonFinite(mean, value); 581 } 582 } 583 return mean; 584 } 585 586 // Serialization helpers 587 588 /** The size of byte array representation in bytes. */ 589 static final int BYTES = (Long.SIZE + Double.SIZE * 4) / Byte.SIZE; 590 591 /** 592 * Gets a byte array representation of this instance. 593 * 594 * <p><b>Note:</b> No guarantees are made regarding stability of the representation between 595 * versions. 596 */ 597 public byte[] toByteArray() { 598 ByteBuffer buff = ByteBuffer.allocate(BYTES).order(ByteOrder.LITTLE_ENDIAN); 599 writeTo(buff); 600 return buff.array(); 601 } 602 603 /** 604 * Writes to the given {@link ByteBuffer} a byte representation of this instance. 605 * 606 * <p><b>Note:</b> No guarantees are made regarding stability of the representation between 607 * versions. 608 * 609 * @param buffer A {@link ByteBuffer} with at least BYTES {@link ByteBuffer#remaining}, ordered as 610 * {@link ByteOrder#LITTLE_ENDIAN}, to which a BYTES-long byte representation of this instance 611 * is written. In the process increases the position of {@link ByteBuffer} by BYTES. 612 */ 613 void writeTo(ByteBuffer buffer) { 614 checkNotNull(buffer); 615 checkArgument( 616 buffer.remaining() >= BYTES, 617 "Expected at least Stats.BYTES = %s remaining , got %s", 618 BYTES, 619 buffer.remaining()); 620 buffer 621 .putLong(count) 622 .putDouble(mean) 623 .putDouble(sumOfSquaresOfDeltas) 624 .putDouble(min) 625 .putDouble(max); 626 } 627 628 /** 629 * Creates a Stats instance from the given byte representation which was obtained by {@link 630 * #toByteArray}. 631 * 632 * <p><b>Note:</b> No guarantees are made regarding stability of the representation between 633 * versions. 634 */ 635 public static Stats fromByteArray(byte[] byteArray) { 636 checkNotNull(byteArray); 637 checkArgument( 638 byteArray.length == BYTES, 639 "Expected Stats.BYTES = %s remaining , got %s", 640 BYTES, 641 byteArray.length); 642 return readFrom(ByteBuffer.wrap(byteArray).order(ByteOrder.LITTLE_ENDIAN)); 643 } 644 645 /** 646 * Creates a Stats instance from the byte representation read from the given {@link ByteBuffer}. 647 * 648 * <p><b>Note:</b> No guarantees are made regarding stability of the representation between 649 * versions. 650 * 651 * @param buffer A {@link ByteBuffer} with at least BYTES {@link ByteBuffer#remaining}, ordered as 652 * {@link ByteOrder#LITTLE_ENDIAN}, from which a BYTES-long byte representation of this 653 * instance is read. In the process increases the position of {@link ByteBuffer} by BYTES. 654 */ 655 static Stats readFrom(ByteBuffer buffer) { 656 checkNotNull(buffer); 657 checkArgument( 658 buffer.remaining() >= BYTES, 659 "Expected at least Stats.BYTES = %s remaining , got %s", 660 BYTES, 661 buffer.remaining()); 662 return new Stats( 663 buffer.getLong(), 664 buffer.getDouble(), 665 buffer.getDouble(), 666 buffer.getDouble(), 667 buffer.getDouble()); 668 } 669 670 private static final long serialVersionUID = 0; 671}