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