public class WordCountMapper extends Mapper{
/*
* LongWritable key:输入的每一行的偏移量 框架读取的
* Text value:输入的每一行的内容
* Context context:上下文对象 用于向reduce发送数据 读取框架给的东西
*
* 调用频率:一行调用一次
* 一个文本100行 这个方法就会调用100次
*/
@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
//读取每一行内容,转换为String
String line = value.toString();
String[] words = line.split("/t");
/*
* 如果要统计 只能统计一行的 并不能统计一个文件的
* 全部发送到reduce端进行统计
* key:单词
* value:1
*/
for(String w:words) {
Text k = new Text(w);
IntWritable v = new IntWritable(1);
context.write(k, v);
}
}
}
public class WordCountReducer extends Reducer{
/*map到reduce之间有一个shuffle的过程(洗牌/将map输出的数据进行打乱 重洗)
Context context 上下文对象 向上承接map 向下输出结果 hdfs/本地
这个函数的调用频率:一组调用一次 有多少组就调用几次
*/
@Override
protected void reduce(Text key, Iterable values,
Context context) throws IOException, InterruptedException {
int sum = 0;
for(IntWritable v:values) {
//将v转为int类型 get hadoop--->java
sum+=v.get();
}
//写出
IntWritable rv = new IntWritable(sum);
context.write(key, rv);
}
}
public class Driver {
/*
* String[] args 代表程序运行过程中接受的参数
* 按照参数的顺序放在数组的下标中
* 第一个参数 -- 数组的下标0的位置
*/
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//加载配置文件
/*
* 优先加载jar包中的 hdfs-default.xml mapred-default.xml ...
* src下的 -site.xml -default.xml
* 代码中的
* 最后加载的最终生效
*/
Configuration conf = new Configuration();
//启动一个job
/*
* job的概念 一个mapreduce程序 封装的map或reduce的相关的配置项
*/
//创建job对象
Job job = Job.getInstance(conf);
//封装上面的job 将自定义的mapper reducer类封装到job上
//指定当前job的入口 main入口
job.setJarByClass(Driver.class);
//参数class 类型 1)类名.class 2)对象。getClass 3)class.forname()
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
//指定mapper的输出的key 和value类型
/*
* 泛型的作用范围:
* 编译时可以进行检查数据类型 运行时泛型自动擦除
*/
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//指定输入 需要处理的文件 添加输入路径
//参数1 job 参数2 输入路径
FileInputFormat.addInputPath(job, new Path("hdfs://hdp01:9000/bb/aa"));
// FileInputFormat.addInputPath(job, new Path(args[0]));
//指定输出路径 输出路径不能存在 否则报错
Path path = new Path("/homework/output01");
FileSystem fs = FileSystem.get(conf);
if(fs.exists(path)) {
fs.delete(path,true);
}
FileOutputFormat.setOutputPath(job,path);
// FileOutputFormat.setOutputPath(job, new Path(args[1]));
//提交job
//这个方法基本不用 不打印日志
//job.submit();
//可以打印日志的 参数代表是否打印运行的进程
job.waitForCompletion(true);
}
}
array.flatMap(x => x.split(" ")).groupBy(x => x).map(x => (x._1, x._2.length))
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object WordCountJar {
def main(args: Array[String]): Unit = {
/**
* 第一步骤: 获取编程入口
* SparkCore: SparkContext
* SparkSql : SQLContext
* SparkStreaming: StreamingContext
*/
val sparkConf = new SparkConf()
sparkConf.setAppName("WordCount")
sparkConf.setMaster(args(0))
val sparkContext = new SparkContext(sparkConf)
/**
* 第二步骤: 通过编程入口,加载数据源获取数据抽象对象
*/
val lines = ssc. socketTextStream(" localhost", 9999)
//textFile:按照Hadoop的LineRecordReader去读取
val lineRDD: RDD[String] = sparkContext.textFile(args(1))
/**
* 第三步骤: 针对数据抽象对象,进行各种计算
*/
val wordRDD: RDD[String] = lineRDD.flatMap(line => line.split(" "))
val wordAndOneRDD: RDD[(String, Int)] = wordRDD.map(word => (word, 1))
val resultRDD: RDD[(String, Int)] = wordAndOneRDD.reduceByKey(_ + _)
val sortResultRDD: RDD[(String, Int)] = resultRDD.sortBy(x => x._2, false)
/**
* 第四步骤: 针对上一步的计算的结果, 进行处理
*/
/*sortResultRDD.foreach(x => {
println(x)
})*/
sortResultRDD.saveAsTextFile(args(2))
/**
* 第五步骤: 资源回收
*/
sparkContext.stop()
}
}
先 启动 TCP socket, 在 Linux 下 通过 nc 启动, 端口 为 9999:
nc -lk 9999
然后 启动 spark- shell: ./bin/ spark- shell,运行代码如下:
// 导入 类
import org. apache. spark. SparkConf
import org. apache. spark. streaming.{ Seconds, StreamingContext}
// 创建 StreamingContext, 基于 shell 下 默认 的 SparkContext
val ssc = new StreamingContext( sc, Seconds( 5))
// 创建 DStream, 这是 Streaming 计算 下 的 RDD
val lines = ssc. socketTextStream(" localhost", 9999)
// 基本 的 操作 函数 与 RDD 同名
val words = lines. flatMap(_. split(" ")) val pairs = words. map( word => (word, 1))
val wordCounts = pairs. reduceByKey(_ + _)
// 打印 结果 到 标准 输出, 只 打印 DStream 中 每个 RDD 的 前 10 个 元素 // 注意, print 不同于 RDD 中的 Action 操作, 不会 触发 真正 的调度 执行
wordCounts. print()
// 这里 才 正式 启动 计算
ssc. start()
// 等待 执行 结束( 出错 或 Ctrl- C 退出)
ssc. awaitTermination()