使用storm分别进行计数和词频统计
计数
直接上代码
public class LocalStormSumTopology {
public static void main(String[] agrs) {
//Topology是通过build模式创建出来的
//storm中的所有作业都是通过topology来指定的
TopologyBuilder builder = new TopologyBuilder();
//在设置bolt到topology时,需要设置该bolt的上游的spout或者bolt的id,这样topology才知道该bolt的执行顺序,有点类似于单向链表结构,
//每一个环节持有上一个环节的引用,在bolt这里是持有上一个环节的id,这样同样可以定位到上一个环节
builder.setSpout("DataSourceSpout", new DataSourceSpout());
builder.setBolt("TotalBolt", new TotalBolt()).shuffleGrouping("DataSourceSpout");
//启动一个本地的Storm集群,不需要搭真正的集群,本地集群使用LocalCluster来提交topology,如果是在生产环境上提交topology,那么使用
//这个类StormSubmitter来代替LocalCluster来提交topology
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("LocalStormSumTopology", new Config(), builder.createTopology());
}
private static final String NUM = "num";
/**
* 发送数据源的spout类,一般是继承BaseRichSpout这个类
*/
public static class DataSourceSpout extends BaseRichSpout {
private SpoutOutputCollector mCollector;
int num;
/**
* 在storm开始的开始工作前回调一次,在这里做初始化
*
* @param conf 配置参数
* @param context 上下文
* @param collector 数据发射器,用来将数据发送到bolt中,类似于rxjava的数据发射器
*/
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
this.mCollector = collector;
}
/**
* 这是一个死循环方法,会自动循环调用,这个方法用来发送数据到下游
*/
public void nextTuple() {
//将数据发射到bolt中,一般使用Values这个类,传入的是可变参数,底层封装成ArrayList
mCollector.emit(new Values(++num));
System.out.println("从spout发射出的数据:" + num);
Utils.sleep(1000);
}
/**
* 声明从spout中发射的数据的字段名,在bolt阶段可以通过这里预设置的字段名进行取值,类似于安卓中的使用sp传输,
* 字段名和发送出来的数据一一对应,这样如果下游需要接收多个数据发射源,那么可以通过该字段名来做区别
*
* @param declarer
*/
public void declareOutputFields(OutputFieldsDeclarer declarer) {
//一般使用Fields来进行封装字段名fields底层封装了ArrayList<String>
declarer.declare(new Fields(NUM));
}
@Override
public void close() {
this.mCollector = null;
}
}
public static class TotalBolt extends BaseRichBolt {
private int sum = 0;
/**
* 初始化方法,跟spout中的open方法类似,只会调用一次,在这里做初始化
*
* @param stormConf
* @param context
* @param collector
*/
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
}
/**
* 每从上游接收到一个数据,就调用该方法回调过来
*
* @param input 用来提取上一个流程传过来的数据
*/
public void execute(Tuple input) {
//通过在上游设置的字段名来获取数据
Integer integerByField = input.getIntegerByField(NUM);
sum += integerByField;
System.out.println("累加的结果是:" + sum);
}
/**
* 为往下游发送的数据加上字段名,方面区别数据的来源
* @param declarer
*/
public void declareOutputFields(OutputFieldsDeclarer declarer) {
}
}
}
词频统计
直接上代码
public class LocalWorldCountStormTopology {
public static void main(String[] agrs) {
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("DataSourceSpout", new DataSourceSpout());
builder.setBolt("CountBolt", new CountBolt()).shuffleGrouping("DataSourceSpout");
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("LocalWorldCountStormTopology", new Config(), builder.createTopology());
}
/**
* 输出每一行文本的spout
*/
public static class DataSourceSpout extends BaseRichSpout {
private SpoutOutputCollector mCollector;
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
this.mCollector = collector;
}
public void nextTuple() {
//通过这个方法,可以获取到某一个文件夹下所有符合规定后缀的文件,并且可以设置是否递归获取
Collection<File> files = FileUtils.listFiles(new File("/Users/teng/Downloads"), new String[]{"txt"}, true);
try {
for (File file : files) {
//因为下一步还需要做切割,因此需要先将文件一行一行取出来,放在String集合中
List<String> lines = FileUtils.readLines(file);
for (String line : lines) {
//使用,进行分割
String[] split = line.split(",");
//发射单词出去
for (String s : split) {
mCollector.emit(new Values(s));
}
}
//执行完成一次之后,需要修改文件名,这样就不用一直执行
FileUtils.moveFile(file, new File(file.getAbsolutePath()+System.currentTimeMillis()));
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
//定义数据的字段名
declarer.declare(new Fields("word"));
}
}
/**
* 统计词频的bolt
*/
public static class CountBolt extends BaseRichBolt {
private Map<String, Integer> map = new HashMap<String, Integer>();
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
}
public void execute(Tuple input) {
String word = input.getStringByField("word");
Integer num = map.get(word);
if (num == null) {
num = 1;
} else {
num++;
}
map.put(word, num);
System.out.println("~~~~~~~~~");
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + "出现的次数为:" + entry.getValue());
}
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
}
}
}
使用storm分别进行计数和词频统计的更多相关文章
- 使用Storm进行词频统计
词频统计 1.需求:读取指定目录的数据,并且实现单词计数功能 2.实现方案: Spout用于读取指定文件夹(目录),读取文件,将文件的每一行发射到Bolt SplitBolt用于接收Spout发射过来 ...
- python瓦登尔湖词频统计
#瓦登尔湖词频统计: import string path = 'D:/python3/Walden.txt' with open(path,'r',encoding= 'utf-8') as tex ...
- c#词频统计命令行程序
这里将用c#写一个关于词频统计的命令行程序. 预计时间分配:输入处理3h.词条排序打印2h.测试3h. 实际时间分配:输入处理1h.词条排序打印2h.测试3h.程序改进优化6h. 下面将讲解程序的完成 ...
- 词频统计 SPEC 20160911
本文档随时可能修改,并且没有另行通知. 请确保每一次在开始修改你的代码前,读标题中的日期,如果晚于你上次阅读, 请重读一次. 老五在寝室吹牛他熟读过<鲁滨逊漂流记>,在女生面前吹牛热爱&l ...
- 软工结对项目之词频统计update
队友 胡展瑞 031602215 作业页面 GitHub 具体分工 111500206 赵畅:负责WordCount的升级,添加新的命令行参数支持(自定义输入输出文件,权重词频统计,词组统计等所有新功 ...
- HW—词频统计
第一次个人作业——词频统计 第一次做这种大作业,明显感觉陌生,各种规范和技能也是第一次使用,希望自己好运. 目录:一.基本要求 二.需求分析及时间估计 三.实现思路及过程 四.测试用例.时间性能分析及 ...
- Hadoop基础学习(一)分析、编写并执行WordCount词频统计程序
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/jiq408694711/article/details/34181439 前面已经在我的Ubuntu ...
- python复合数据类型以及英文词频统计
这个作业的要求来自于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2753. 1.列表,元组,字典,集合分别如何增删改查及遍历. 列 ...
- 作业3-个人项目<词频统计>
上了一天的课,现在终于可以静下来更新我的博客了. 越来越发现,写博客是一种享受.来看看这次小林老师的“作战任务”. 词频统计 单词: 包含有4个或4个以上的字 ...
随机推荐
- html中meta标签及用法理解
自己一直想成为高级前端开发工程师,而自学.奈何最近感觉自学收效甚微,一度迷茫. 不破不立,打算改变这样的状态. 春节后上班第一天,今年打算好好实现自己的前端梦想. 重新整理.总结前端技术. 废话,就不 ...
- Redmine基础: 邮件配置
1.用文本编辑器打开 D:\Bitnami\redmine-2.6.5-0\apps\redmine\htdocs\config\configuration.yml 文件,找到以下内容: 2.配置邮件 ...
- 传统IO与NIO(channel-to-channel)文件拷贝的探索与性能比对
Channel-to-channel传输是可以极其快速的,特别是在底层操作系统提供本地支持的时候.某些操作系统可以不必通过用户空间传递数据而进行直接的数据传输.对于大量的数据传输,这会是一个巨大的帮助 ...
- Yii2重置密码
//Yii框架下hash密码正确的比较方法$result = Yii::$app->security->validatePassword($password, $hash);echo $r ...
- linux shell 和linux 命令的区别?windows shell 和 windows 命令呢?
shell翻译成壳的意思,它是包裹在linux内核外层的,一个可通过一系列的linux命令对操作系统发出相关指令的人机界面. shell可以通过其条件语句和循环语句等,把一系列linux命令结合在一起 ...
- SmileyFace——基于OpenCV的人脸人眼检测、面部识别程序
项目地址 https://github.com/guoyaohua/SmileyFace 开发环境 Visual Studio 2010 MFC + OpenCV 功能描述 静态图像人脸检测 视频人脸 ...
- JVM笔记4-对象的创建
1.对象的创建过程: 1.new 类名 2.根据new的参数在常量池中定位一个类的符号的引用. 3.如果没找到这个符号的引用,说明类还没有被加载.则进行类的加载,解析和初始化 4.虚拟机为对象分配内存 ...
- R+NLP︱text2vec包——四类文本挖掘相似性指标 RWMD、cosine、Jaccard 、Euclidean (三,相似距离)
要学的东西太多,无笔记不能学~~ 欢迎关注公众号,一起分享学习笔记,记录每一颗"贝壳"~ --------------------------- 在之前的开篇提到了text2vec ...
- PCI和PCIE插槽有什么区别?
PCI是Peripheral Component Interconnect(外设部件互连标准)的缩写,它是目前个人电脑中使用最为广泛的接口,几乎所有的主板产品上都带有这种插槽.PCI插槽也是主板带有最 ...
- Flex读取txt文件中的内容报错
Flex读取txt文件中的内容 1.具体错误如下 2.错误原因 读取文件不存在 var file:File = new File(File.applicationDirectory.nativePat ...