You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Spark中如何按列唯一名称排序?求各流派评分最多用户实现

解决每个流派下评分次数最多用户的问题

我明白你的需求啦——要找出每个流派中评分次数最多的用户,而且同一个用户可以出现在多个流派的结果里对吧?你的现有代码确实没达到预期,因为它只是把所有(userId, genres)的组合按评分次数降序排列,但没有针对每个流派单独提取出次数最多的那个用户。

问题根源

你的代码:

Dataset<Row> group = exploded.groupBy("userId", "genres").count().orderBy(org.apache.spark.sql.functions.col("count").desc());

这段代码是把每个用户-流派组合的评分次数算出来后做了全局排序,但并没有按流派分组去筛选每个组内的Top1用户,所以你看到的结果是所有组合的排序,而不是每个流派各自的Top用户。

正确解决方案:用窗口函数实现分组取Top1

要实现需求,我们需要借助窗口函数(Window Function),按流派分组,在每个组内按评分次数降序排序,然后取每个组里排名第一的记录。具体步骤如下:

  1. 首先导入Spark窗口函数相关的类:
import org.apache.spark.sql.expressions.Window;
import org.apache.spark.sql.functions;
  1. 定义窗口规范:按genres分区(也就是每个流派作为一个独立的组),然后按count降序排序:
Window genreWindow = Window.partitionBy("genres")
                          .orderBy(functions.col("count").desc());
  1. 基于分组统计的结果,添加排名列,再过滤出每个流派的Top1用户:
Dataset<Row> topUserPerGenre = exploded.groupBy("userId", "genres")
    .count() // 先统计每个用户在每个流派的评分次数
    .withColumn("rank", functions.row_number().over(genreWindow)) // 给每个流派内的记录按次数排名
    .filter(functions.col("rank").equalTo(1)) // 只保留每个流派排名第一的记录
    .drop("rank") // 移除不需要的排名列
    .orderBy("genres"); // 最后按流派排序,方便查看结果

额外细节:处理并列第一的情况

如果某个流派下有多个用户的评分次数相同(并列第一),上面的row_number()只会保留其中一个用户。如果你想保留所有并列第一的用户,可以把row_number()换成rank()或者dense_rank():

// 用rank()保留所有并列第一的用户
.withColumn("rank", functions.rank().over(genreWindow))

这样就能精准得到每个流派下评分次数最多的用户啦,同一个用户完全可以出现在多个流派的结果里哦!

内容的提问来源于stack exchange,提问作者A.Koparanski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:49:28