Spark 计算总销量

Spark 计算总销量

题目:

某电商平台存储了所有商品的销售数据,平台希望能够找到销量最好的前 N 个商品。通过分析销售记录,帮助平台决策哪些商品需要更多的推广资源。

假设你得到了一个商品销售记录的文本文件

复制代码
product_id, product_name, quantity, sale_date
1, "Smartphone", 10, "2024-11-01"
2, "Laptop", 5, "2024-11-02"
3, "T-Shirt", 25, "2024-11-03"
4, "Smartwatch", 8, "2024-11-04"
5, "Headphones", 12, "2024-11-05"
1, "Smartphone", 15, "2024-11-06"
2, "Laptop", 10, "2024-11-07"
3, "T-Shirt", 10, "2024-11-08"

各字段含义:

product_id: 商品ID

product_name: 商品名称

quantity: 销售数量

sale_date: 销售日期

任务:

计算总销量:计算每个商品的总销量,输出如下。

复制代码
product_id  product_name  total_sales
1           Smartphone    25
2           Laptop        15
3           T-Shirt       35
4           Smartwatch    8
5           Headphones    12

找出销量最高的前 N 个商品:根据计算出的销量,找出前 N 个销售量最多的商品,N 由用户输入。N=3时输出如下:

复制代码
product_id  product_name total_sales
3           T-Shirt       35
1          Smartphone     25
2           Laptop        15

运行

  1. 在桌面创建文件buy_count.txt,输入文本内容
  2. Java代码
java 复制代码
import org.apache.spark.api.java.*;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.function.PairFunction;
import org.apache.spark.api.java.function.Function2;
import scala.Serializable;
import scala.Tuple2;
import java.util.Scanner;

public class Test02 {
    /*
    * Serializable
    * 标记一个类可以被序列化,
    * 即可以将其状态转换为字节流,
    * 以便进行持久化存储或在网络上传输
    * */
    static  class  Product implements Serializable{
        int product_id;
        String product_name;
        int quantity;

        @Override
        public String toString() {
            return  String.format("%-10s %-20s %-10s", product_id, product_name, quantity);
        }
    }
    public static void main(String[] args) {
        // 文件路径
        // 获取用户的主目录并构建绝对路径
        String userHome = System.getProperty("user.home");
        String logFile = "file://" + userHome + "/Desktop/spark_test.txt";
//        String logFile = "file:///Desktop/spark_test.txt";
        // SparkConf 对象
        // setMaster("local")表示应用程序将在本地模式下运行
        // setAppName("SimpleApp")设置了应用程序的名称为SimpleApp
        SparkConf conf=new SparkConf().setMaster("local").setAppName("SimpleApp");
        // JavaSparkContext对象,它是与Spark交互的主要入口点。它接收前面创建的SparkConf对象作为参数
        JavaSparkContext sc=new JavaSparkContext(conf);
        // sc.textFile(logFile)加载文本文件内容
        // .cache()方法会将此RDD缓存起来以便后续重复使用时能更快访问
        JavaRDD<String> linesRDD = sc.textFile(logFile).cache();
        /*
        * 按商品分组
        * JavaPairRDD 键值对
        * PairFunction用于定义将输入对象转换为键值对的逻辑
        * filter 方法对linesRDD中的每一行执行过滤(删除标题行)
        * mapToPair 会对每一行进行处理,生成键值对
        * 以product_name做键,Product对象做值
        * */
        JavaPairRDD<Integer, Product> productRDD = linesRDD.filter(new Function<String, Boolean>() {
            public Boolean call(String line) {
                return !line.contains("product_id");
            }
        }).mapToPair(new PairFunction<String, Integer, Product>(){
            @Override
            public Tuple2<Integer, Product> call(String line) throws Exception {
                String[] fields = line.split(", ");
                Product product = new Product();
                product.product_id = Integer.parseInt(fields[0]);
                product.product_name = fields[1].replace("\"", "");
                product.quantity = Integer.parseInt(fields[2]);
                return new Tuple2<Integer, Product>(product.product_id, product);
            }
        });

        System.out.printf("%-10s %-20s %-10s%n", "product_id", "product_name", "total_sales");
        productRDD.foreach(tuple -> {
            Product value = tuple._2;
            System.out.println(value);
        });
        System.out.println("------------------------------------");

        /*
        * 合并同一商品的数量
        * */
        JavaPairRDD<Integer, Product> productRDD2 = productRDD.reduceByKey(new Function2<Product, Product, Product>(){
            @Override
            public Product call(Product product, Product product2) throws Exception {
                product2.quantity += product.quantity;
                return product2;
            }
        });
        // 按照商品id升序排序
        JavaPairRDD<Integer, Product> fourproductRankDescRDD = productRDD2.sortByKey(true);

        System.out.printf("%-10s %-20s %-10s%n", "product_id", "product_name", "total_sales");
        fourproductRankDescRDD.foreach(tuple -> {
            Product value = tuple._2;
            System.out.println(value);
        });
        // 将 JavaPairRDD 转换为 JavaRDD<Product>
        JavaRDD<Product> productRDD3 = productRDD2.values();
        // 按照 quantity 降序排序
        JavaRDD<Product> sortedByQuantityRDD = productRDD3.sortBy(product -> product.quantity, false, 1);
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入要显示的前N名商品:");
        int N =  scanner.nextInt();
        System.out.printf("%-10s %-20s %-10s%n", "product_id", "product_name", "total_sales");
        sortedByQuantityRDD.take(N).forEach(product -> System.out.println(product));
    }
}
  1. IDEA打包:https://blog.csdn.net/kelekele111/article/details/123047189
  2. 终端运行
shell 复制代码
/usr/local/spark/bin/spark-submit  ~/Desktop/Spark.jar
相关推荐
互联网中的一颗神经元9 小时前
04 — 安全撤销:改错了怎么退回去
大数据·安全·elasticsearch
marvelyu12 小时前
每天10分钟学会OceanBase系列(Day 20):跨机房容灾实战——构建多数据中心高可用架构
java·大数据·数据库
ZCBUS实时计算12 小时前
金融证券实时数仓建设实践:轻量化实时计算平台落地,实现交易数据端到端秒级处理
大数据·数据库·数据仓库·金融·flink·dba·etl
海上小飞龙13 小时前
Redis 分布式锁原理:从 SET NX EX 到 Redisson 看门狗
数据库·redis·分布式
烟雨江南78513 小时前
2026汽车制造与新能源整车柔性产线Agentic-Workflow白皮书:跨APS_MES_ERP多智能体动态排产与装配容错实战
大数据·网络·人工智能·自动化·ai客服·企业agent
明达智控技术14 小时前
国产PLC、远程IO模块在食品包装机的应用
分布式·自动化
zhexunnb15 小时前
专业SAP ERP实施,赋能制造企业构建一体化数字内核
大数据
明源云16 小时前
租赁管理系统软件推荐:如何选到真正好用的不动产租赁管理软件
大数据·人工智能·架构
Meya112717 小时前
机柜可视化不靠复杂坐标!三参数轻量化 U 位管理系统落地思路
大数据·人工智能
行思理17 小时前
OPPO PUSH新消息分类,新手教程
大数据·人工智能·推送