wordCount的三种实现方式(mapreduce,scala,spark)

文章目录

    • 1. mapreduce实现
      • Mapper类
      • Reducer类
      • Driver类
    • 2. scala
    • 3.spark离线统计
    • 4.Spark实时统计

1. mapreduce实现

Mapper类

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);
		}
	}
}

Reducer类

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);
	}	
}

Driver类

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); 	
	}
}

2. scala

	array.flatMap(x => x.split(" ")).groupBy(x => x).map(x => (x._1, x._2.length))

3.spark离线统计

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()
  }
}

4.Spark实时统计

先 启动 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()

你可能感兴趣的:(spark)