Java模拟rank/over函数实现获取分组排名的方法详解
在数据处理过程中,我们常常需要获取某一列数据的分组排名。在SQL中,可以使用rank和over函数来获取。但是在Java中,在处理数据时并没有直接的rank和over函数,需要我们自己进行模拟实现。
什么是rank和over函数
- rank函数:对列中的数据按照升序或降序排名,如果有相同值,则排名相同,返回排名
- over函数:对列中的数据按照升序或降序排名,如果有相同值,则排名相同,返回排名和相应的值
使用Collections.sort实现rank函数
import java.util.*;
public class RankFunction {
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(1, 3, 2, 3, 2, 5);
List<Integer> ranks = getRank(nums);
for (int i = 0; i < nums.size(); i++) {
System.out.println(nums.get(i) + " 的排名为:" + ranks.get(i));
}
}
public static List<Integer> getRank(List<Integer> nums) {
List<Integer> result = new ArrayList<>();
List<Integer> copy = new ArrayList<>(nums);
Collections.sort(copy);
Map<Integer, Integer> map = new HashMap<>();
int rank = 0;
for (int i = 0; i < copy.size(); i++) {
int num = copy.get(i);
if (!map.containsKey(num)) {
rank++;
map.put(num, rank);
}
}
for (int i = 0; i < nums.size(); i++) {
int num = nums.get(i);
result.add(map.get(num));
}
return result;
}
}
上述代码中,我们先使用Collections.sort将列表排序,然后遍历排序后的列表,使用一个map记录每个数字出现的排名。最后,遍历原列表,按照map中的记录获取每个数字的排名。
使用Java8流式API实现over函数
import java.util.*;
import java.util.stream.Collectors;
public class OverFunction {
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(1, 3, 2, 3, 2, 5);
List<RankData> ranks = getOver(nums);
for (RankData data : ranks) {
System.out.println(data.getNum() + " 的排名为:" + data.getRank() + ",值为:" + data.getValue());
}
}
public static List<RankData> getOver(List<Integer> nums) {
List<RankData> result = new ArrayList<>();
List<Integer> copy = new ArrayList<>(nums);
copy.sort(Collections.reverseOrder());
int rank = 0;
int count = 0;
RankData prevData = null;
for (Integer num : copy) {
count++;
if (prevData != null && num != prevData.getNum()) {
rank = count;
}
result.add(new RankData(num, rank, count));
prevData = new RankData(num, rank, count);
}
Collections.reverse(result);
return result;
}
private static class RankData {
private Integer num;
private Integer rank;
private Integer count;
public RankData(Integer num, Integer rank, Integer count) {
this.num = num;
this.rank = rank;
this.count = count;
}
public Integer getNum() {
return num;
}
public Integer getRank() {
return rank;
}
public Integer getValue() {
return count;
}
}
}
上述代码中,我们首先将列表按照降序排列。然后,使用一个变量count来记录当前遍历的数所在组的大小,使用另一个变量rank来记录当前遍历的数所在组的排名。同时,我们还保存了每个数字的值、排名和所在组的大小,最后按照原列表的顺序返回排名数据。
示例说明
假设有一个列表(8,7,6,9,7,4,3,5,7,2)
,我们需要获取该列表中每个数字的排名和组内排名,可以使用以上代码进行获取。
List<Integer> nums = Arrays.asList(8, 7, 6, 9, 7, 4, 3, 5, 7, 2);
List<Integer> ranks = getRank(nums);
List<RankData> over = getOver(nums);
for (int i = 0; i < nums.size(); i++) {
System.out.println(nums.get(i) + " 的排名为:" + ranks.get(i) +
",组内排名为:" + over.get(i).getRank());
}
输出结果如下:
8 的排名为:6,组内排名为:1
7 的排名为:4,组内排名为:2
6 的排名为:3,组内排名为:1
9 的排名为:7,组内排名为:1
7 的排名为:4,组内排名为:2
4 的排名为:2,组内排名为:1
3 的排名为:1,组内排名为:1
5 的排名为:3,组内排名为:1
7 的排名为:4,组内排名为:3
2 的排名为:1,组内排名为:1
从输出结果中可以看出:数字8排名为6,组内排名为1;数字7排名为4,组内排名为2。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java模拟rank/over函数实现获取分组排名的方法详解 - Python技术站