Coverage Summary for Class: Stats (com.google.common.math)

Class Class, % Method, % Line, %
Stats 0% (0/1) 0% (0/34) 0% (0/137)


1 /* 2  * Copyright (C) 2012 The Guava Authors 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5  * in compliance with the License. You may obtain a copy of the License at 6  * 7  * http://www.apache.org/licenses/LICENSE-2.0 8  * 9  * Unless required by applicable law or agreed to in writing, software distributed under the License 10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11  * or implied. See the License for the specific language governing permissions and limitations under 12  * the License. 13  */ 14  15 package com.google.common.math; 16  17 import static com.google.common.base.Preconditions.checkArgument; 18 import static com.google.common.base.Preconditions.checkNotNull; 19 import static com.google.common.base.Preconditions.checkState; 20 import static com.google.common.math.DoubleUtils.ensureNonNegative; 21 import static com.google.common.math.StatsAccumulator.calculateNewMeanNonFinite; 22 import static com.google.common.primitives.Doubles.isFinite; 23 import static java.lang.Double.NaN; 24 import static java.lang.Double.doubleToLongBits; 25 import static java.lang.Double.isNaN; 26  27 import com.google.common.annotations.Beta; 28 import com.google.common.annotations.GwtIncompatible; 29 import com.google.common.base.MoreObjects; 30 import com.google.common.base.Objects; 31 import java.io.Serializable; 32 import java.nio.ByteBuffer; 33 import java.nio.ByteOrder; 34 import java.util.Iterator; 35 import java.util.stream.Collector; 36 import java.util.stream.DoubleStream; 37 import java.util.stream.IntStream; 38 import java.util.stream.LongStream; 39 import javax.annotation.CheckForNull; 40  41 /** 42  * A bundle of statistical summary values -- sum, count, mean/average, min and max, and several 43  * forms of variance -- that were computed from a single set of zero or more floating-point values. 44  * 45  * <p>There are two ways to obtain a {@code Stats} instance: 46  * 47  * <ul> 48  * <li>If all the values you want to summarize are already known, use the appropriate {@code 49  * Stats.of} factory method below. Primitive arrays, iterables and iterators of any kind of 50  * {@code Number}, and primitive varargs are supported. 51  * <li>Or, to avoid storing up all the data first, create a {@link StatsAccumulator} instance, 52  * feed values to it as you get them, then call {@link StatsAccumulator#snapshot}. 53  * </ul> 54  * 55  * <p>Static convenience methods called {@code meanOf} are also provided for users who wish to 56  * calculate <i>only</i> the mean. 57  * 58  * <p><b>Java 8 users:</b> If you are not using any of the variance statistics, you may wish to use 59  * built-in JDK libraries instead of this class. 60  * 61  * @author Pete Gillin 62  * @author Kevin Bourrillion 63  * @since 20.0 64  */ 65 @Beta 66 @GwtIncompatible 67 @ElementTypesAreNonnullByDefault 68 public final class Stats implements Serializable { 69  70  private final long count; 71  private final double mean; 72  private final double sumOfSquaresOfDeltas; 73  private final double min; 74  private final double max; 75  76  /** 77  * Internal constructor. Users should use {@link #of} or {@link StatsAccumulator#snapshot}. 78  * 79  * <p>To ensure that the created instance obeys its contract, the parameters should satisfy the 80  * following constraints. This is the callers responsibility and is not enforced here. 81  * 82  * <ul> 83  * <li>If {@code count} is 0, {@code mean} may have any finite value (its only usage will be to 84  * get multiplied by 0 to calculate the sum), and the other parameters may have any values 85  * (they will not be used). 86  * <li>If {@code count} is 1, {@code sumOfSquaresOfDeltas} must be exactly 0.0 or {@link 87  * Double#NaN}. 88  * </ul> 89  */ 90  Stats(long count, double mean, double sumOfSquaresOfDeltas, double min, double max) { 91  this.count = count; 92  this.mean = mean; 93  this.sumOfSquaresOfDeltas = sumOfSquaresOfDeltas; 94  this.min = min; 95  this.max = max; 96  } 97  98  /** 99  * 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 acummulator = new StatsAccumulator(); 130  acummulator.addAll(values); 131  return acummulator.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 acummulator = new StatsAccumulator(); 141  acummulator.addAll(values); 142  return acummulator.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 acummulator = new StatsAccumulator(); 153  acummulator.addAll(values); 154  return acummulator.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 28.2 166  */ 167  public static Stats of(DoubleStream values) { 168  return values 169  .collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll) 170  .snapshot(); 171  } 172  173  /** 174  * Returns statistics over a dataset containing the given values. The stream will be completely 175  * consumed by this method. 176  * 177  * <p>If you have a {@code Stream<Integer>} rather than an {@code IntStream}, you should collect 178  * the values using {@link #toStats()} instead. 179  * 180  * @param values a series of values 181  * @since 28.2 182  */ 183  public static Stats of(IntStream values) { 184  return values 185  .collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll) 186  .snapshot(); 187  } 188  189  /** 190  * Returns statistics over a dataset containing the given values. The stream will be completely 191  * consumed by this method. 192  * 193  * <p>If you have a {@code Stream<Long>} rather than a {@code LongStream}, you should collect the 194  * values using {@link #toStats()} instead. 195  * 196  * @param values a series of values, which will be converted to {@code double} values (this may 197  * cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15)) 198  * @since 28.2 199  */ 200  public static Stats of(LongStream values) { 201  return values 202  .collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll) 203  .snapshot(); 204  } 205  206  /** 207  * Returns a {@link Collector} which accumulates statistics from a {@link java.util.stream.Stream} 208  * of any type of boxed {@link Number} into a {@link Stats}. Use by calling {@code 209  * boxedNumericStream.collect(toStats())}. The numbers will be converted to {@code double} values 210  * (which may cause loss of precision). 211  * 212  * <p>If you have any of the primitive streams {@code DoubleStream}, {@code IntStream}, or {@code 213  * LongStream}, you should use the factory method {@link #of} instead. 214  * 215  * @since 28.2 216  */ 217  public static Collector<Number, StatsAccumulator, Stats> toStats() { 218  return Collector.of( 219  StatsAccumulator::new, 220  (a, x) -> a.add(x.doubleValue()), 221  (l, r) -> { 222  l.addAll(r); 223  return l; 224  }, 225  StatsAccumulator::snapshot, 226  Collector.Characteristics.UNORDERED); 227  } 228  229  /** Returns the number of values. */ 230  public long count() { 231  return count; 232  } 233  234  /** 235  * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the 236  * values. The count must be non-zero. 237  * 238  * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of 239  * the arithmetic mean of the population. 240  * 241  * <h3>Non-finite values</h3> 242  * 243  * <p>If the dataset contains {@link Double#NaN} then the result is {@link Double#NaN}. If it 244  * contains both {@link Double#POSITIVE_INFINITY} and {@link Double#NEGATIVE_INFINITY} then the 245  * result is {@link Double#NaN}. If it contains {@link Double#POSITIVE_INFINITY} and finite values 246  * only or {@link Double#POSITIVE_INFINITY} only, the result is {@link Double#POSITIVE_INFINITY}. 247  * If it contains {@link Double#NEGATIVE_INFINITY} and finite values only or {@link 248  * Double#NEGATIVE_INFINITY} only, the result is {@link Double#NEGATIVE_INFINITY}. 249  * 250  * <p>If you only want to calculate the mean, use {@link #meanOf} instead of creating a {@link 251  * Stats} instance. 252  * 253  * @throws IllegalStateException if the dataset is empty 254  */ 255  public double mean() { 256  checkState(count != 0); 257  return mean; 258  } 259  260  /** 261  * Returns the sum of the values. 262  * 263  * <h3>Non-finite values</h3> 264  * 265  * <p>If the dataset contains {@link Double#NaN} then the result is {@link Double#NaN}. If it 266  * contains both {@link Double#POSITIVE_INFINITY} and {@link Double#NEGATIVE_INFINITY} then the 267  * result is {@link Double#NaN}. If it contains {@link Double#POSITIVE_INFINITY} and finite values 268  * only or {@link Double#POSITIVE_INFINITY} only, the result is {@link Double#POSITIVE_INFINITY}. 269  * If it contains {@link Double#NEGATIVE_INFINITY} and finite values only or {@link 270  * Double#NEGATIVE_INFINITY} only, the result is {@link Double#NEGATIVE_INFINITY}. 271  */ 272  public double sum() { 273  return mean * count; 274  } 275  276  /** 277  * Returns the <a href="http://en.wikipedia.org/wiki/Variance#Population_variance">population 278  * variance</a> of the values. The count must be non-zero. 279  * 280  * <p>This is guaranteed to return zero if the dataset contains only exactly one finite value. It 281  * is not guaranteed to return zero when the dataset consists of the same value multiple times, 282  * due to numerical errors. However, it is guaranteed never to return a negative result. 283  * 284  * <h3>Non-finite values</h3> 285  * 286  * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link 287  * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}. 288  * 289  * @throws IllegalStateException if the dataset is empty 290  */ 291  public double populationVariance() { 292  checkState(count > 0); 293  if (isNaN(sumOfSquaresOfDeltas)) { 294  return NaN; 295  } 296  if (count == 1) { 297  return 0.0; 298  } 299  return ensureNonNegative(sumOfSquaresOfDeltas) / count(); 300  } 301  302  /** 303  * Returns the <a 304  * href="http://en.wikipedia.org/wiki/Standard_deviation#Definition_of_population_values"> 305  * population standard deviation</a> of the values. The count must be non-zero. 306  * 307  * <p>This is guaranteed to return zero if the dataset contains only exactly one finite value. It 308  * is not guaranteed to return zero when the dataset consists of the same value multiple times, 309  * due to numerical errors. However, it is guaranteed never to return a negative result. 310  * 311  * <h3>Non-finite values</h3> 312  * 313  * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link 314  * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}. 315  * 316  * @throws IllegalStateException if the dataset is empty 317  */ 318  public double populationStandardDeviation() { 319  return Math.sqrt(populationVariance()); 320  } 321  322  /** 323  * Returns the <a href="http://en.wikipedia.org/wiki/Variance#Sample_variance">unbiased sample 324  * variance</a> of the values. If this dataset is a sample drawn from a population, this is an 325  * unbiased estimator of the population variance of the population. The count must be greater than 326  * one. 327  * 328  * <p>This is not guaranteed to return zero when the dataset consists of the same value multiple 329  * times, due to numerical errors. However, it is guaranteed never to return a negative result. 330  * 331  * <h3>Non-finite values</h3> 332  * 333  * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link 334  * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}. 335  * 336  * @throws IllegalStateException if the dataset is empty or contains a single value 337  */ 338  public double sampleVariance() { 339  checkState(count > 1); 340  if (isNaN(sumOfSquaresOfDeltas)) { 341  return NaN; 342  } 343  return ensureNonNegative(sumOfSquaresOfDeltas) / (count - 1); 344  } 345  346  /** 347  * Returns the <a 348  * href="http://en.wikipedia.org/wiki/Standard_deviation#Corrected_sample_standard_deviation"> 349  * corrected sample standard deviation</a> of the values. If this dataset is a sample drawn from a 350  * population, this is an estimator of the population standard deviation of the population which 351  * is less biased than {@link #populationStandardDeviation()} (the unbiased estimator depends on 352  * the distribution). The count must be greater than one. 353  * 354  * <p>This is not guaranteed to return zero when the dataset consists of the same value multiple 355  * times, due to numerical errors. However, it is guaranteed never to return a negative result. 356  * 357  * <h3>Non-finite values</h3> 358  * 359  * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link 360  * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}. 361  * 362  * @throws IllegalStateException if the dataset is empty or contains a single value 363  */ 364  public double sampleStandardDeviation() { 365  return Math.sqrt(sampleVariance()); 366  } 367  368  /** 369  * Returns the lowest value in the dataset. The count must be non-zero. 370  * 371  * <h3>Non-finite values</h3> 372  * 373  * <p>If the dataset contains {@link Double#NaN} then the result is {@link Double#NaN}. If it 374  * contains {@link Double#NEGATIVE_INFINITY} and not {@link Double#NaN} then the result is {@link 375  * Double#NEGATIVE_INFINITY}. If it contains {@link Double#POSITIVE_INFINITY} and finite values 376  * only then the result is the lowest finite value. If it contains {@link 377  * Double#POSITIVE_INFINITY} only then the result is {@link Double#POSITIVE_INFINITY}. 378  * 379  * @throws IllegalStateException if the dataset is empty 380  */ 381  public double min() { 382  checkState(count != 0); 383  return min; 384  } 385  386  /** 387  * Returns the highest value in the dataset. The count must be non-zero. 388  * 389  * <h3>Non-finite values</h3> 390  * 391  * <p>If the dataset contains {@link Double#NaN} then the result is {@link Double#NaN}. If it 392  * contains {@link Double#POSITIVE_INFINITY} and not {@link Double#NaN} then the result is {@link 393  * Double#POSITIVE_INFINITY}. If it contains {@link Double#NEGATIVE_INFINITY} and finite values 394  * only then the result is the highest finite value. If it contains {@link 395  * Double#NEGATIVE_INFINITY} only then the result is {@link Double#NEGATIVE_INFINITY}. 396  * 397  * @throws IllegalStateException if the dataset is empty 398  */ 399  public double max() { 400  checkState(count != 0); 401  return max; 402  } 403  404  /** 405  * {@inheritDoc} 406  * 407  * <p><b>Note:</b> This tests exact equality of the calculated statistics, including the floating 408  * point values. Two instances are guaranteed to be considered equal if one is copied from the 409  * other using {@code second = new StatsAccumulator().addAll(first).snapshot()}, if both were 410  * obtained by calling {@code snapshot()} on the same {@link StatsAccumulator} without adding any 411  * values in between the two calls, or if one is obtained from the other after round-tripping 412  * through java serialization. However, floating point rounding errors mean that it may be false 413  * for some instances where the statistics are mathematically equal, including instances 414  * constructed from the same values in a different order... or (in the general case) even in the 415  * same order. (It is guaranteed to return true for instances constructed from the same values in 416  * the same order if {@code strictfp} is in effect, or if the system architecture guarantees 417  * {@code strictfp}-like semantics.) 418  */ 419  @Override 420  public boolean equals(@CheckForNull Object obj) { 421  if (obj == null) { 422  return false; 423  } 424  if (getClass() != obj.getClass()) { 425  return false; 426  } 427  Stats other = (Stats) obj; 428  return count == other.count 429  && doubleToLongBits(mean) == doubleToLongBits(other.mean) 430  && doubleToLongBits(sumOfSquaresOfDeltas) == doubleToLongBits(other.sumOfSquaresOfDeltas) 431  && doubleToLongBits(min) == doubleToLongBits(other.min) 432  && doubleToLongBits(max) == doubleToLongBits(other.max); 433  } 434  435  /** 436  * {@inheritDoc} 437  * 438  * <p><b>Note:</b> This hash code is consistent with exact equality of the calculated statistics, 439  * including the floating point values. See the note on {@link #equals} for details. 440  */ 441  @Override 442  public int hashCode() { 443  return Objects.hashCode(count, mean, sumOfSquaresOfDeltas, min, max); 444  } 445  446  @Override 447  public String toString() { 448  if (count() > 0) { 449  return MoreObjects.toStringHelper(this) 450  .add("count", count) 451  .add("mean", mean) 452  .add("populationStandardDeviation", populationStandardDeviation()) 453  .add("min", min) 454  .add("max", max) 455  .toString(); 456  } else { 457  return MoreObjects.toStringHelper(this).add("count", count).toString(); 458  } 459  } 460  461  double sumOfSquaresOfDeltas() { 462  return sumOfSquaresOfDeltas; 463  } 464  465  /** 466  * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the 467  * values. The count must be non-zero. 468  * 469  * <p>The definition of the mean is the same as {@link Stats#mean}. 470  * 471  * @param values a series of values, which will be converted to {@code double} values (this may 472  * cause loss of precision) 473  * @throws IllegalArgumentException if the dataset is empty 474  */ 475  public static double meanOf(Iterable<? extends Number> values) { 476  return meanOf(values.iterator()); 477  } 478  479  /** 480  * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the 481  * values. The count must be non-zero. 482  * 483  * <p>The definition of the mean is the same as {@link Stats#mean}. 484  * 485  * @param values a series of values, which will be converted to {@code double} values (this may 486  * cause loss of precision) 487  * @throws IllegalArgumentException if the dataset is empty 488  */ 489  public static double meanOf(Iterator<? extends Number> values) { 490  checkArgument(values.hasNext()); 491  long count = 1; 492  double mean = values.next().doubleValue(); 493  while (values.hasNext()) { 494  double value = values.next().doubleValue(); 495  count++; 496  if (isFinite(value) && isFinite(mean)) { 497  // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15) 498  mean += (value - mean) / count; 499  } else { 500  mean = calculateNewMeanNonFinite(mean, value); 501  } 502  } 503  return mean; 504  } 505  506  /** 507  * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the 508  * values. The count must be non-zero. 509  * 510  * <p>The definition of the mean is the same as {@link Stats#mean}. 511  * 512  * @param values a series of values 513  * @throws IllegalArgumentException if the dataset is empty 514  */ 515  public static double meanOf(double... values) { 516  checkArgument(values.length > 0); 517  double mean = values[0]; 518  for (int index = 1; index < values.length; index++) { 519  double value = values[index]; 520  if (isFinite(value) && isFinite(mean)) { 521  // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15) 522  mean += (value - mean) / (index + 1); 523  } else { 524  mean = calculateNewMeanNonFinite(mean, value); 525  } 526  } 527  return mean; 528  } 529  530  /** 531  * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the 532  * values. The count must be non-zero. 533  * 534  * <p>The definition of the mean is the same as {@link Stats#mean}. 535  * 536  * @param values a series of values 537  * @throws IllegalArgumentException if the dataset is empty 538  */ 539  public static double meanOf(int... values) { 540  checkArgument(values.length > 0); 541  double mean = values[0]; 542  for (int index = 1; index < values.length; index++) { 543  double value = values[index]; 544  if (isFinite(value) && isFinite(mean)) { 545  // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15) 546  mean += (value - mean) / (index + 1); 547  } else { 548  mean = calculateNewMeanNonFinite(mean, value); 549  } 550  } 551  return mean; 552  } 553  554  /** 555  * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the 556  * values. The count must be non-zero. 557  * 558  * <p>The definition of the mean is the same as {@link Stats#mean}. 559  * 560  * @param values a series of values, which will be converted to {@code double} values (this may 561  * cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15)) 562  * @throws IllegalArgumentException if the dataset is empty 563  */ 564  public static double meanOf(long... values) { 565  checkArgument(values.length > 0); 566  double mean = values[0]; 567  for (int index = 1; index < values.length; index++) { 568  double value = values[index]; 569  if (isFinite(value) && isFinite(mean)) { 570  // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15) 571  mean += (value - mean) / (index + 1); 572  } else { 573  mean = calculateNewMeanNonFinite(mean, value); 574  } 575  } 576  return mean; 577  } 578  579  // Serialization helpers 580  581  /** The size of byte array representation in bytes. */ 582  static final int BYTES = (Long.SIZE + Double.SIZE * 4) / Byte.SIZE; 583  584  /** 585  * Gets a byte array representation of this instance. 586  * 587  * <p><b>Note:</b> No guarantees are made regarding stability of the representation between 588  * versions. 589  */ 590  public byte[] toByteArray() { 591  ByteBuffer buff = ByteBuffer.allocate(BYTES).order(ByteOrder.LITTLE_ENDIAN); 592  writeTo(buff); 593  return buff.array(); 594  } 595  596  /** 597  * Writes to the given {@link ByteBuffer} a byte representation of this instance. 598  * 599  * <p><b>Note:</b> No guarantees are made regarding stability of the representation between 600  * versions. 601  * 602  * @param buffer A {@link ByteBuffer} with at least BYTES {@link ByteBuffer#remaining}, ordered as 603  * {@link ByteOrder#LITTLE_ENDIAN}, to which a BYTES-long byte representation of this instance 604  * is written. In the process increases the position of {@link ByteBuffer} by BYTES. 605  */ 606  void writeTo(ByteBuffer buffer) { 607  checkNotNull(buffer); 608  checkArgument( 609  buffer.remaining() >= BYTES, 610  "Expected at least Stats.BYTES = %s remaining , got %s", 611  BYTES, 612  buffer.remaining()); 613  buffer 614  .putLong(count) 615  .putDouble(mean) 616  .putDouble(sumOfSquaresOfDeltas) 617  .putDouble(min) 618  .putDouble(max); 619  } 620  621  /** 622  * Creates a Stats instance from the given byte representation which was obtained by {@link 623  * #toByteArray}. 624  * 625  * <p><b>Note:</b> No guarantees are made regarding stability of the representation between 626  * versions. 627  */ 628  public static Stats fromByteArray(byte[] byteArray) { 629  checkNotNull(byteArray); 630  checkArgument( 631  byteArray.length == BYTES, 632  "Expected Stats.BYTES = %s remaining , got %s", 633  BYTES, 634  byteArray.length); 635  return readFrom(ByteBuffer.wrap(byteArray).order(ByteOrder.LITTLE_ENDIAN)); 636  } 637  638  /** 639  * Creates a Stats instance from the byte representation read from the given {@link ByteBuffer}. 640  * 641  * <p><b>Note:</b> No guarantees are made regarding stability of the representation between 642  * versions. 643  * 644  * @param buffer A {@link ByteBuffer} with at least BYTES {@link ByteBuffer#remaining}, ordered as 645  * {@link ByteOrder#LITTLE_ENDIAN}, from which a BYTES-long byte representation of this 646  * instance is read. In the process increases the position of {@link ByteBuffer} by BYTES. 647  */ 648  static Stats readFrom(ByteBuffer buffer) { 649  checkNotNull(buffer); 650  checkArgument( 651  buffer.remaining() >= BYTES, 652  "Expected at least Stats.BYTES = %s remaining , got %s", 653  BYTES, 654  buffer.remaining()); 655  return new Stats( 656  buffer.getLong(), 657  buffer.getDouble(), 658  buffer.getDouble(), 659  buffer.getDouble(), 660  buffer.getDouble()); 661  } 662  663  private static final long serialVersionUID = 0; 664 }