Skip to content

Commit 786c3d8

Browse files
hshankarcpovirk
authored andcommitted
Change Quantiles' compute() methods for multiple indexes to return a map with entries in the order in which the indexes were provided in the call to indexes().
Fixes #2989 RELNOTES=`math`: `Quantiles` `compute()` methods which return a `Map` now return a map with entries in the same order in which the indexes were provided. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=272459623
1 parent 188a218 commit 786c3d8

File tree

4 files changed

+70
-26
lines changed

4 files changed

+70
-26
lines changed

android/guava-tests/test/com/google/common/math/QuantilesTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,18 @@ public void testScale_indexes_varargs_compute_integerCollection() {
290290
8, SIXTEEN_SQUARES_DECILE_8);
291291
}
292292

293+
public void testScale_indexes_varargs_compute_indexOrderIsMaintained() {
294+
assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(SIXTEEN_SQUARES_INTEGERS))
295+
.comparingValuesUsing(QUANTILE_CORRESPONDENCE)
296+
.containsExactly(
297+
0, SIXTEEN_SQUARES_MIN,
298+
10, SIXTEEN_SQUARES_MAX,
299+
5, SIXTEEN_SQUARES_MEDIAN,
300+
1, SIXTEEN_SQUARES_DECILE_1,
301+
8, SIXTEEN_SQUARES_DECILE_8)
302+
.inOrder();
303+
}
304+
293305
public void testScale_indexes_varargs_compute_doubleVarargs() {
294306
double[] dataset = Doubles.toArray(SIXTEEN_SQUARES_DOUBLES);
295307
assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(dataset))

android/guava/src/com/google/common/math/Quantiles.java

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import com.google.common.primitives.Ints;
2828
import java.math.RoundingMode;
2929
import java.util.Collection;
30-
import java.util.HashMap;
30+
import java.util.LinkedHashMap;
3131
import java.util.Map;
3232

3333
/**
@@ -331,8 +331,10 @@ private ScaleAndIndexes(int scale, int[] indexes) {
331331
* @param dataset the dataset to do the calculation on, which must be non-empty, which will be
332332
* cast to doubles (with any associated lost of precision), and which will not be mutated by
333333
* this call (it is copied instead)
334-
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
335-
* the values the corresponding quantile values
334+
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
335+
* indexes, and the values the corresponding quantile values. When iterating, entries in the
336+
* map are ordered by quantile index in the same order they were passed to the {@code
337+
* indexes} method.
336338
*/
337339
public Map<Integer, Double> compute(Collection<? extends Number> dataset) {
338340
return computeInPlace(Doubles.toArray(dataset));
@@ -343,8 +345,10 @@ public Map<Integer, Double> compute(Collection<? extends Number> dataset) {
343345
*
344346
* @param dataset the dataset to do the calculation on, which must be non-empty, which will not
345347
* be mutated by this call (it is copied instead)
346-
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
347-
* the values the corresponding quantile values
348+
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
349+
* indexes, and the values the corresponding quantile values. When iterating, entries in the
350+
* map are ordered by quantile index in the same order they were passed to the {@code
351+
* indexes} method.
348352
*/
349353
public Map<Integer, Double> compute(double... dataset) {
350354
return computeInPlace(dataset.clone());
@@ -356,8 +360,10 @@ public Map<Integer, Double> compute(double... dataset) {
356360
* @param dataset the dataset to do the calculation on, which must be non-empty, which will be
357361
* cast to doubles (with any associated lost of precision), and which will not be mutated by
358362
* this call (it is copied instead)
359-
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
360-
* the values the corresponding quantile values
363+
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
364+
* indexes, and the values the corresponding quantile values. When iterating, entries in the
365+
* map are ordered by quantile index in the same order they were passed to the {@code
366+
* indexes} method.
361367
*/
362368
public Map<Integer, Double> compute(long... dataset) {
363369
return computeInPlace(longsToDoubles(dataset));
@@ -368,8 +374,10 @@ public Map<Integer, Double> compute(long... dataset) {
368374
*
369375
* @param dataset the dataset to do the calculation on, which must be non-empty, which will be
370376
* cast to doubles, and which will not be mutated by this call (it is copied instead)
371-
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
372-
* the values the corresponding quantile values
377+
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
378+
* indexes, and the values the corresponding quantile values. When iterating, entries in the
379+
* map are ordered by quantile index in the same order they were passed to the {@code
380+
* indexes} method.
373381
*/
374382
public Map<Integer, Double> compute(int... dataset) {
375383
return computeInPlace(intsToDoubles(dataset));
@@ -380,13 +388,15 @@ public Map<Integer, Double> compute(int... dataset) {
380388
*
381389
* @param dataset the dataset to do the calculation on, which must be non-empty, and which will
382390
* be arbitrarily reordered by this method call
383-
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
384-
* the values the corresponding quantile values
391+
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
392+
* indexes, and the values the corresponding quantile values. When iterating, entries in the
393+
* map are ordered by quantile index in the same order that the indexes were passed to the
394+
* {@code indexes} method.
385395
*/
386396
public Map<Integer, Double> computeInPlace(double... dataset) {
387397
checkArgument(dataset.length > 0, "Cannot calculate quantiles of an empty dataset");
388398
if (containsNaN(dataset)) {
389-
Map<Integer, Double> nanMap = new HashMap<>();
399+
Map<Integer, Double> nanMap = new LinkedHashMap<>();
390400
for (int index : indexes) {
391401
nanMap.put(index, NaN);
392402
}
@@ -425,7 +435,7 @@ public Map<Integer, Double> computeInPlace(double... dataset) {
425435
sort(requiredSelections, 0, requiredSelectionsCount);
426436
selectAllInPlace(
427437
requiredSelections, 0, requiredSelectionsCount - 1, dataset, 0, dataset.length - 1);
428-
Map<Integer, Double> ret = new HashMap<>();
438+
Map<Integer, Double> ret = new LinkedHashMap<>();
429439
for (int i = 0; i < indexes.length; i++) {
430440
int quotient = quotients[i];
431441
int remainder = remainders[i];

guava-tests/test/com/google/common/math/QuantilesTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,18 @@ public void testScale_indexes_varargs_compute_integerCollection() {
290290
8, SIXTEEN_SQUARES_DECILE_8);
291291
}
292292

293+
public void testScale_indexes_varargs_compute_indexOrderIsMaintained() {
294+
assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(SIXTEEN_SQUARES_INTEGERS))
295+
.comparingValuesUsing(QUANTILE_CORRESPONDENCE)
296+
.containsExactly(
297+
0, SIXTEEN_SQUARES_MIN,
298+
10, SIXTEEN_SQUARES_MAX,
299+
5, SIXTEEN_SQUARES_MEDIAN,
300+
1, SIXTEEN_SQUARES_DECILE_1,
301+
8, SIXTEEN_SQUARES_DECILE_8)
302+
.inOrder();
303+
}
304+
293305
public void testScale_indexes_varargs_compute_doubleVarargs() {
294306
double[] dataset = Doubles.toArray(SIXTEEN_SQUARES_DOUBLES);
295307
assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(dataset))

guava/src/com/google/common/math/Quantiles.java

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import com.google.common.primitives.Ints;
2828
import java.math.RoundingMode;
2929
import java.util.Collection;
30-
import java.util.HashMap;
30+
import java.util.LinkedHashMap;
3131
import java.util.Map;
3232

3333
/**
@@ -331,8 +331,10 @@ private ScaleAndIndexes(int scale, int[] indexes) {
331331
* @param dataset the dataset to do the calculation on, which must be non-empty, which will be
332332
* cast to doubles (with any associated lost of precision), and which will not be mutated by
333333
* this call (it is copied instead)
334-
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
335-
* the values the corresponding quantile values
334+
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
335+
* indexes, and the values the corresponding quantile values. When iterating, entries in the
336+
* map are ordered by quantile index in the same order they were passed to the {@code
337+
* indexes} method.
336338
*/
337339
public Map<Integer, Double> compute(Collection<? extends Number> dataset) {
338340
return computeInPlace(Doubles.toArray(dataset));
@@ -343,8 +345,10 @@ public Map<Integer, Double> compute(Collection<? extends Number> dataset) {
343345
*
344346
* @param dataset the dataset to do the calculation on, which must be non-empty, which will not
345347
* be mutated by this call (it is copied instead)
346-
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
347-
* the values the corresponding quantile values
348+
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
349+
* indexes, and the values the corresponding quantile values. When iterating, entries in the
350+
* map are ordered by quantile index in the same order they were passed to the {@code
351+
* indexes} method.
348352
*/
349353
public Map<Integer, Double> compute(double... dataset) {
350354
return computeInPlace(dataset.clone());
@@ -356,8 +360,10 @@ public Map<Integer, Double> compute(double... dataset) {
356360
* @param dataset the dataset to do the calculation on, which must be non-empty, which will be
357361
* cast to doubles (with any associated lost of precision), and which will not be mutated by
358362
* this call (it is copied instead)
359-
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
360-
* the values the corresponding quantile values
363+
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
364+
* indexes, and the values the corresponding quantile values. When iterating, entries in the
365+
* map are ordered by quantile index in the same order they were passed to the {@code
366+
* indexes} method.
361367
*/
362368
public Map<Integer, Double> compute(long... dataset) {
363369
return computeInPlace(longsToDoubles(dataset));
@@ -368,8 +374,10 @@ public Map<Integer, Double> compute(long... dataset) {
368374
*
369375
* @param dataset the dataset to do the calculation on, which must be non-empty, which will be
370376
* cast to doubles, and which will not be mutated by this call (it is copied instead)
371-
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
372-
* the values the corresponding quantile values
377+
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
378+
* indexes, and the values the corresponding quantile values. When iterating, entries in the
379+
* map are ordered by quantile index in the same order they were passed to the {@code
380+
* indexes} method.
373381
*/
374382
public Map<Integer, Double> compute(int... dataset) {
375383
return computeInPlace(intsToDoubles(dataset));
@@ -380,13 +388,15 @@ public Map<Integer, Double> compute(int... dataset) {
380388
*
381389
* @param dataset the dataset to do the calculation on, which must be non-empty, and which will
382390
* be arbitrarily reordered by this method call
383-
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
384-
* the values the corresponding quantile values
391+
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
392+
* indexes, and the values the corresponding quantile values. When iterating, entries in the
393+
* map are ordered by quantile index in the same order that the indexes were passed to the
394+
* {@code indexes} method.
385395
*/
386396
public Map<Integer, Double> computeInPlace(double... dataset) {
387397
checkArgument(dataset.length > 0, "Cannot calculate quantiles of an empty dataset");
388398
if (containsNaN(dataset)) {
389-
Map<Integer, Double> nanMap = new HashMap<>();
399+
Map<Integer, Double> nanMap = new LinkedHashMap<>();
390400
for (int index : indexes) {
391401
nanMap.put(index, NaN);
392402
}
@@ -425,7 +435,7 @@ public Map<Integer, Double> computeInPlace(double... dataset) {
425435
sort(requiredSelections, 0, requiredSelectionsCount);
426436
selectAllInPlace(
427437
requiredSelections, 0, requiredSelectionsCount - 1, dataset, 0, dataset.length - 1);
428-
Map<Integer, Double> ret = new HashMap<>();
438+
Map<Integer, Double> ret = new LinkedHashMap<>();
429439
for (int i = 0; i < indexes.length; i++) {
430440
int quotient = quotients[i];
431441
int remainder = remainders[i];

0 commit comments

Comments
 (0)