【Java】SparkRDD算子案例:统计出每一个省份广告被点击次数的TOP3

题目描述

统计出每一个省份广告被点击次数的TOP3
假设这些信息都存储在一个文件里,并且该文件的格式如下,时间戳,省份,城市,用户,广告,中间字段使用空格分割。

构造样例数据

1684484483 省份1 北京 1001 鞋子
1684484483 省份1 上海 1002 衣服
1684484483 省份3 广州 1003 电脑
1684484483 省份4 深圳 1004 手机
1684484483 省份4 成都 1005 眼镜
1684484483 省份6 天津 1001 鞋子
1684484483 省份8 重庆 1002 衣服
1684484483 省份8 杭州 1003 电脑
1684484483 省份8 南京 1004 手机
1684484483 省份10 厦门 1005 眼镜
1684484483 省份1 北京 1001 鞋子
1684484483 省份1 上海 1002 衣服
1684484483 省份3 广州 1003 电脑
1684484483 省份4 深圳 1004 手机
1684484483 省份4 成都 1005 眼镜
1684484483 省份6 天津 1001 鞋子
1684484483 省份8 重庆 1002 衣服
1684484483 省份8 杭州 1003 电脑
1684484483 省份8 南京 1004 手机
1684484483 省份10 厦门 1005 眼镜
1684484483 省份1 北京 1001 鞋子
1684484483 省份1 上海 1002 衣服
1684484483 省份3 广州 1003 电脑
1684484483 省份4 深圳 1004 手机
1684484483 省份4 成都 1005 眼镜
1684484483 省份6 天津 1001 鞋子
1684484483 省份8 重庆 1002 衣服
1684484483 省份8 杭州 1003 电脑
1684484483 省份8 南京 1004 手机
1684484483 省份10 厦门 1005 眼镜

Java Spark代码实现

package T051801;


import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.PairFunction;
import scala.Tuple2;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class AdClickTop3 {


    public static void main(String[] args) {

        // 创建SparkConf和JavaSparkContext
        SparkConf conf = new SparkConf();

        // 设置应用名称
        conf.setAppName("AdClickTop3");

        // 设置运行模式
        // local:表示在本地单机上以单线程模式运行
        // local[*]:表示在本地单机上以多线程模式运行,线程数由系统自动决定
        // spark://HOST:PORT:表示连接到指定的 Spark 集群运行
        // mesos://HOST:PORT:表示连接到指定的 Mesos 集群运行
        // yarn:表示在 YARN 集群上运行
        conf.setMaster("local[*]");

        // 创建 JavaSpark 上下文对象
        JavaSparkContext sc = new JavaSparkContext(conf);

        // 读取数据文件
        JavaRDD<String> fileRDD = sc.textFile("ad.txt");

        // 按照空格分割数据取得省份和广告 ((省份, 广告), 1)
        JavaPairRDD<Tuple2<String, String>, Integer> pairRDD = fileRDD.mapToPair(s -> new Tuple2<>(new Tuple2<>(s.split(" ")[1], s.split(" ")[4]), 1));

        // 计算点击数 ((省份, 广告), 点击数和)
        JavaPairRDD<Tuple2<String, String>, Integer> reduceRDD = pairRDD.reduceByKey(Integer::sum);

        // 转换 key 的结构 ((省份, 广告), 点击数和) => (省份, (广告, 点击数和))
        JavaPairRDD<String, Tuple2<String, Integer>> provinceAdClicksRDD = reduceRDD.mapToPair((PairFunction<Tuple2<Tuple2<String, String>, Integer>, String, Tuple2<String, Integer>>) tuple -> {
            String province = tuple._1()._1();
            String ad = tuple._1()._2();
            int clicks = tuple._2();
            return new Tuple2<>(province, new Tuple2<>(ad, clicks));
        });

        // 按照省份进行分组,将同一省份的元素放到同一个 Iterable 中
        JavaPairRDD<String, Iterable<Tuple2<String, Integer>>> provinceAdClicksListRDD = provinceAdClicksRDD.groupByKey();

        // 获取每个城市 Top3 点击广告
        JavaPairRDD<String, Iterable<Tuple2<String, Integer>>> topTwoAdsByProvinceRDD = provinceAdClicksListRDD.mapValues((Function<Iterable<Tuple2<String, Integer>>, Iterable<Tuple2<String, Integer>>>) tuple2s -> {
            ArrayList<Tuple2<String, Integer>> tuple2s1 = new ArrayList<>();
            for (Tuple2<String, Integer> next : tuple2s) {
                tuple2s1.add(next);
            }

            // 降序排列
            tuple2s1.sort((o1, o2) -> o2._2() - o1._2());
            ArrayList<Tuple2<String, Integer>> t = new ArrayList<>();
            Iterator<Tuple2<String, Integer>> iterator1 = tuple2s1.iterator();

            // 遍历前 Top3 点击广告添加到 List
            int i = 0;
            while (iterator1.hasNext() & i < 3) {
                t.add(iterator1.next());
                i++;
            }

            return t;
        });

        // 计算结果收集到 List
        List<Tuple2<String, Iterable<Tuple2<String, Integer>>>> data = topTwoAdsByProvinceRDD.collect();

        // 输出结果
        data.forEach(System.out::println);

        sc.stop();

    }


}

结果验证

在这里插入图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
这个项目实战的目标是实时统计最近1小时的广告点击量,并将结果写入Redis中。 为了实现这个目标,我们可以使用Spark Streaming来处理实时据流。首先,我们需要从Kafka中读取广告点击事件流,并将其转换为DStream对象。然后,我们可以使用窗口操作来计算最近1小时的点击量。最后,我们可以将结果写入Redis中。 具体实现步骤如下: 1. 创建Spark Streaming上下文对象,并从Kafka中读取广告点击事件流。 2. 将事件流转换为DStream对象,并使用窗口操作计算最近1小时的点击量。 3. 将结果写入Redis中。可以使用Redis的Java客户端库Jedis来实现。 下面是一个简单的代码示例: ```scala import org.apache.spark.streaming._ import org.apache.spark.streaming.kafka._ import redis.clients.jedis.Jedis val ssc = new StreamingContext(sparkConf, Seconds(5)) val kafkaParams = Map("metadata.broker.list" -> brokers) val topics = Set("ad-clicks") val adClicks = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder]( ssc, kafkaParams, topics) val adClicksByHour = adClicks.map { case (_, value) => val fields = value.split(",") val timestamp = fields(0).toLong val hour = timestamp / 3600 (hour, 1) }.reduceByKeyAndWindow(_ + _, _ - _, Minutes(60), Seconds(5)) adClicksByHour.foreachRDD { rdd => rdd.foreachPartition { partition => val jedis = new Jedis(redisHost, redisPort) partition.foreach { case (hour, count) => jedis.hset("ad-clicks", hour.toString, count.toString) } jedis.close() } } ssc.start() ssc.awaitTermination() ``` 在这个示例中,我们首先从Kafka中读取广告点击事件流,并将其转换为DStream对象。然后,我们使用map操作将每个事件的时间戳转换为小时,并将其作为键,值为1。接下来,我们使用reduceByKeyAndWindow操作计算最近1小时的点击量,并将结果写入Redis中。 需要注意的是,我们使用foreachPartition操作来避免在每个分区中创建多个Redis连接。这可以提高性能并减少资源消耗。 总之,使用Spark Streaming和Redis可以轻松实现最近1小时广告点击量的实时统计和写入。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天析

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值