举例见:
package com.mytest; import java.math.RoundingMode; import java.util.List; import org.apache.commons.math3.stat.ranking.NaturalRanking; import com.google.common.base.Function; import com.google.common.collect.Lists; import com.google.common.math.DoubleMath; import com.google.common.primitives.Doubles; /** * 分数排名 * @author kakaka * */ public class ScoreOrdering { public static void main(String[] args) { double[] score = { 45, 78, 99, 86, 77, 75, 95, 56, 86, 63, 71, 77 }; NaturalRanking ranking = new NaturalRanking(); double[] result = ranking.rank(score); System.out.println("排名前分数: " + Doubles.asList(score)); System.out.println("排名后名次: " + Doubles.asList(result)); // 分数相同的排名处理,可以做名次舍入处理,java.math.RoundingMode List<Double> ranks = Doubles.asList(result); // RoundingMode.UP 排名归大,归后(归下) List<Integer> rankUp = Lists.transform(ranks, new Function<Double, Integer>() { public Integer apply(Double input) { return DoubleMath.roundToInt(input, RoundingMode.UP); } }); System.out.println("排名后名次处理(归后): " + rankUp); // RoundingMode.DOWN 排名归小,归前(归上) List<Integer> rankDown = Lists.transform(ranks, new Function<Double, Integer>() { public Integer apply(Double input) { return DoubleMath.roundToInt(input, RoundingMode.DOWN); } }); System.out.println("排名后名次处理(归前): " + rankDown); } }
结果见:
排名前分数: [45.0, 78.0, 99.0, 86.0, 77.0, 75.0, 95.0, 56.0, 86.0, 63.0, 71.0, 77.0] 排名后名次: [1.0, 8.0, 12.0, 9.5, 6.5, 5.0, 11.0, 2.0, 9.5, 3.0, 4.0, 6.5] 排名后名次处理(归后): [1, 8, 12, 10, 7, 5, 11, 2, 10, 3, 4, 7] 排名后名次处理(归前): [1, 8, 12, 9, 6, 5, 11, 2, 9, 3, 4, 6]
考虑到分数由大到小排名,将数组统一处理成负数,并且有更简洁的办法,留意NaturalRanking的TiesStrategy策略:
double[] score = { 45, 78, 99, 86, 77, 75, 95, 56, 86, 63, 71, 77 }; List<Double> score1 = Lists.transform(Doubles.asList(score), new Function<Double, Double>() { public Double apply(Double input) { return 0-input; // 统一处理成负数 } }); //double[] score1 = {-45, -78, -99, -86, -77, -75, -95, -56, -86, -63, -71, -77 }; NaturalRanking ranking1 = new NaturalRanking(); double[] result1 = ranking1.rank(Doubles.toArray(score1)); System.out.println("排名前分数: " + score1); System.out.println("排名后名次: " + Doubles.asList(result1)); //分数相同策略,打结策略 ranking1 = new NaturalRanking(TiesStrategy.MAXIMUM); result1 = ranking1.rank(Doubles.toArray(score1)); System.out.println("分数相同排名后归后: " + Doubles.asList(result1)); ranking1 = new NaturalRanking(TiesStrategy.MINIMUM); result1 = ranking1.rank(Doubles.toArray(score1)); System.out.println("分数相同排名后归前: " + Doubles.asList(result1));
结果为:
排名前分数: [-45.0, -78.0, -99.0, -86.0, -77.0, -75.0, -95.0, -56.0, -86.0, -63.0, -71.0, -77.0] 排名后名次: [12.0, 5.0, 1.0, 3.5, 6.5, 8.0, 2.0, 11.0, 3.5, 10.0, 9.0, 6.5] 分数相同排名后归后: [12.0, 5.0, 1.0, 4.0, 7.0, 8.0, 2.0, 11.0, 4.0, 10.0, 9.0, 7.0] 分数相同排名后归前: [12.0, 5.0, 1.0, 3.0, 6.0, 8.0, 2.0, 11.0, 3.0, 10.0, 9.0, 6.0]
分数排序处理,主要利用com.google.common.collect.Ordering, 处理比较简洁
double[] score = { 45, 78, 99, 86, 77, 75, 95, 56, 86, 63, 71, 77 }; // 自然排序,数字按大小,日期按先后排序 Ordering<Double> ordering = Ordering.natural(); List<Double> scoreOrdering = ordering.sortedCopy(Doubles.asList(score)); System.out.println("分数排序(由小到大): " + scoreOrdering); Ordering<Double> reOrdering = Ordering.natural().reverse(); List<Double> scoreOrdering1 = reOrdering.sortedCopy(Doubles.asList(score)); System.out.println("分数排序(由大到小): " + scoreOrdering1);
结果
分数排序(由小到大): [45.0, 56.0, 63.0, 71.0, 75.0, 77.0, 77.0, 78.0, 86.0, 86.0, 95.0, 99.0] 分数排序(由大到小): [99.0, 95.0, 86.0, 86.0, 78.0, 77.0, 77.0, 75.0, 71.0, 63.0, 56.0, 45.0]