经常会有这样的需求 : 第一名 一个奖励, 第2-3名 一个奖励,第4-6名 , 一个奖励, 第7到10名 一个奖励, 第11-30 一个奖励, 第31-100名 一个奖励,第101-300 一个奖励, 类似这样的分段排名,对应不同的奖励
public static void main(String[] args) {
RangeMap<Integer, String> map = testRange();
System.out.println(map);
int[] ranks = {1, 10, 30, 50, 5002};
for (int rank : ranks) {
String rewardId = map.get(rank);
System.out.println("rank===="+ rank + "===rewardId====" + rewardId);
}
}
public static RangeMap<Integer, String> testRange() {
int limit = 5001;
String rewards = "[{\"Rank\":1,\"Reward\":\"reward_1\"},{\"Rank\":2,\"Reward\":\"reward_2\"},{\"Rank\":4,\"Reward\":\"reward_3\"},{\"Rank\":7,\"Reward\":\"reward_4\"},{\"Rank\":11,\"Reward\":\"reward_5\"},{\"Rank\":31,\"Reward\":\"reward_6\"},{\"Rank\":101,\"Reward\":\"reward_7\"},{\"Rank\":301,\"Reward\":\"reward_8\"},{\"Rank\":1001,\"Reward\":\"reward_9\"}]";
// rank -> rewardId
JSONArray rewardsArr = JSONArray.fromObject(rewards);
//构造排名对应奖励
RangeMap<Integer, String> rangeMap = TreeRangeMap.create();
int size = rewardsArr.size();
for (int i = 0; i < size; i++) {
JSONObject rewardDetailArr = rewardsArr.getJSONObject(i);
if (!rewardDetailArr.containsKey("Rank") || !rewardDetailArr.containsKey("Reward")) {
// throw new KOFDataConfigException("奖励配置有误!");
}
int nextIndex = Math.min(i + 1, size - 1); // 1, 8, 2, 8, 8=8
int min = 0;
int max = 0;
String rewardId = null;
JSONObject rewardNextDetailArr = rewardsArr.getJSONObject(nextIndex);
if (!rewardNextDetailArr.containsKey("Rank") || !rewardNextDetailArr.containsKey("Reward")) {
// throw new KOFDataConfigException("奖励配置有误!");
}
min = rewardDetailArr.getInt("Rank");
//处理是不是 最后一个
if (nextIndex != size - 1) {
max = rewardNextDetailArr.getInt("Rank");
rewardId = rewardDetailArr.getString("Reward");
} else {
max = limit;
rewardId = rewardNextDetailArr.getString("Reward");
}
//{x | a <= x < b} //1001 5000
rangeMap.put(Range.closedOpen(min, max), rewardId);
}
return rangeMap;
}
输出结果:
[[1‥2)=reward_1, [2‥4)=reward_2, [4‥7)=reward_3, [7‥11)=reward_4, [11‥31)=reward_5, [31‥101)=reward_6, [101‥301)=reward_7, [301‥1001)=reward_9, [1001‥5001)=reward_9]
rank====1===rewardId====reward_1
rank====10===rewardId====reward_4
rank====30===rewardId====reward_5
rank====50===rewardId====reward_6
rank====5002===rewardId====null
以往的做法就是: for循环 rewards 数组 然后 根据排名 获得奖励
原来还有一种 更简单的做法
在Google Guava官方API上面可以得知:RangeMap是一种集合类型( collection type),它将不相交、且不为空的Range(key)映射给一个值(Value)。和RangeSet不一样,RangeMap不可以将相邻的区间合并,即使这个区间映射的值是一样的。
和RangeSet一样,实现RangeMap也是一个接口,实现它的也只有两个类,分别为mmutableRangeMap和TreeRangeMap。用的多的还是TreeRangeMap,下面主要以TreeRangeMap来说明RangeMap。对RangeMap可以添加、删除其中的对象,操作如下:
public RangeMap<Integer, String> testRangeMap() {
RangeMap<Integer, String> rangeMap = TreeRangeMap.create();
rangeMap.put(Range.closed(1, 10), "aaa");
System.out.println(rangeMap);
rangeMap.put(Range.open(3, 6), "bbb");
System.out.println(rangeMap);
rangeMap.put(Range.openClosed(10, 20), "aaa");
System.out.println(rangeMap);
rangeMap.put(Range.closed(20, 20), "aaa");
System.out.println(rangeMap);
rangeMap.remove(Range.closed(5, 11));
System.out.println(rangeMap);
return rangeMap;
}
[[1‥10]=aaa]
[[1‥3]=aaa, (3‥6)=bbb, [6‥10]=aaa]
[[1‥3]=aaa, (3‥6)=bbb, [6‥10]=aaa, (10‥20]=aaa]
[[1‥3]=aaa, (3‥6)=bbb, [6‥10]=aaa, (10‥20)=aaa, [20‥20]=aaa]
[[1‥3]=aaa, (3‥5)=bbb, (11‥20)=aaa, [20‥20]=aaa]
从结果中可以看出,RangeMap中的每一个Range都对应一个value。注意观察运行的结果,(10‥20)=aaa, [20‥20]=aaa,是没有被合并的!