Java模拟rank/over函数实现获取分组排名的方法详解

在数据处理过程中,我们常常需要获取某一列数据的分组排名。在SQL中,可以使用rank和over函数来获取。但是在Java中,在处理数据时并没有直接的rank和over函数,需要我们自己进行模拟实现。

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函数实现获取分组排名的方法详解

基础教程推荐