01.Spark(spark shell实现word count)

spark shell实现word count

scala>sc
[签名]
res0:org.apache.spark.sparkContext=org.apache.Spark.SparkContext@3331800f(对象hash码地址)
scala>sc.  +tab键它能把所有方法补齐![sc方法]


加载一个文档计算单词的个数
RDD(Resilient Distributed dataset)弹性分布式数据集当于List

scala> sc.textFile
def textFile(path:String,minPartitions:Int):org.apache.spark.rdd.RDD[String]
scala>sc.textFile

RDD的方法

Spark中提供了八十多种高级算子,很大一部分在RDD上提供了这些算子。
scala> rdd1.foreach
[签名]
foreach foreachAsync foreachPartition foreachPartitionAsync
scala> rdd1.foreach
[签名]
// (f: String=>Unit)高阶函数
   def foreach(f: String=>Unit):Unit//循环里面传了一个高阶函数,函数是一个。字符串作为参数,没有返回值
scala> rdd1.foreach(println(_))//把这个文件打印出来,此时rdd1相当于一个集合。那这个集合的每一个元素相当于每一行。
rdd在工作的时候,通过sc.textFole(...)去加载得到了rdd1.计算单词个数该如何
它每一个元素是一行,把一行的元素压扁.压扁是什么意思?如果不压扁会出现什么情况?
如果不压扁,那么这个集合就相当于嵌套的集合。每一个元素成数组了。把元素流出来放入外围的集合里面去。
第二步操作:做压扁操作,既然压扁。那么这个函数的返回值一定是可以迭代的量。不然就不能压扁。就因为它返回的是一个迭代的量是一种集合。它才把集合种的每一元素流到外面的集合里面去。这就是压扁。如果压扁成功了那么集合就,每个单词一行一行的了。压扁是rdd的方法。
scala> rdd1.collect    //collect 收集,一收集它就变成了数组。每一个元素就变成了数组,每一个元素用逗号(,)隔开
[签名]
rest2:Array[String]=Array(helo  world,helo  world,helo  world,helo  world,helo  world,helo  world)
scala> rdd1.flatMap  //压扁
[签名]
//(f:String=> TraversableOnce[U]这个也是一个高阶函数从字符串到TraversableOnce是可以进行一次迭代的意思
 def flatMap[U](f:String=> TraversableOnce[U](implicit evidence$4:scla.reflect.CLassTag[U]):org.apache.spark.rdd.RDD[U])//implicit evidence$4:这个是隐式参数(柯里化)。flatMap是柯里化函数参数是隐式参数。只要传递第一个值就好了。
//如果要压扁每一行都要line,然后每一行切割split
scala> val rdd2= rdd1.flatMap(line=>{line.split(" ")})
[签名]
rdd2:org.apache.spark.rdd.RDD[String]=MapPartitionsRDD[2]at flatMap at <console>:26
scala> rdd.collect  //收集一些
res3:Array[String]=Array(helo  world,helo  world,helo  world,helo  world,helo  world,helo  world)
然后分组,按单独分组在Spark中 标一成对。如果变成了两个元素的元组。那就是对偶。对于rdd2来讲,每一个元素就是一个单词。这样一来单词就成了单词就是key了。标一成对只要把同一个key的值累加起来就行 了。把每一个单词变成变成单词和1的对偶。
//rdd3
scala> val rdd3=rdd2.map(word=>{(word,1)}) //它是一个高阶,它是一个变换变成(word,1)
[签名]
rdd3:org.apache.spark.rdd.RDD[(String,Int)]=MapPartitionsRDD[3]at map at<console>:28
scala>rdd3.collect  //再收集一些
[签名]
res4:Arry[String,Int]=Array((hello,1),(word1asdf,1),(hellod,1),(word13,1),(hello2,1),(word231,1),(hell2o,1),(word231,1),(hel234lo,1),(wor234d1,1))
scala> val rdd4=rdd3.reduceByKey
[签名]
//func:(Int,Int)一个高阶函数,两个整数到一个整数的变换,
def reduceByKey(func:(Int,Int)=>Int):org.apache.spark.rdd.RDD[(String,Int)]
def reduceByKey(func:(Int,Int)=>Int,numPartitions:Int):org.apache.spark.rdd.RDD[(String,Int)]
def reduceByKey(partitioner:org.apache.spark.Partitioner,func:(Int,Int)=>Int):org.apache.spark.rdd.RDD[(String,Int)]
//val rdd4=rdd3.reduceByKey((a:Int,b:Int)=>{})这个是匿名函数
scala> val rdd4=rdd3.reduceByKey((a:Int,b:Int)=>{a+b})
scala> rdd4.collect  //收集一下,Spark比scala方便多了,scala提供了ByKey的方法。直接按Key去聚合值实现了wordd count的操作。
下一步就打印了,collect  返回了一个数组 
scala>rdd4.collect 
[签名]
//可以传一个偏函数PartialFunction[(String,Int),implicit evidence$29:scala带了一个隐式参数,返回值:Array
def collect[U](f:PartialFunction[(String,Int),U])(implicit evidence$29:scala.reflect.ClassTag[U]):org.apache.spark.rdd.RDD[U]
def collect():Array[(String,Int)]  //这些是方法链编程
//先加载文件,然后压扁下划线切割按空来切紧接着标一成对(参数只在右侧出现一次的就可以用_了map((_,1)))
scala>sc.textFile("fil e:///home/centos/1.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).collect
[签名]
注意了:凡是ByKey的方法都是按照Key去聚合它的值。
-----------------------------------------------------------------
在SparkShell下实现了word count
可以用分组来实现
scala>rdd1.collect  //是每一行的值
scala>rdd2.collect  //压扁后的单词
scala>rdd3.collect  //标一成对的单词  这里没有map都是List,所以这里的key是可以重复的。
scala>rdd3.groupByKey
[签名]
//返回值RDD每个元素变成了单词和整数值的迭代Iteerable[Int]),它把同一个key下面的所有整数值聚在了一起(n多个1)
def groupByKey(): org.apache.spark.rdd.RDD[(String,Iteerable[Int])]
def groupByKey(numPartitions:Int):org.apache.spark.rdd.RDD[(String,Iterable[Int])]
def groupByKey(partitioner:org.apache.spark.Partitioner):org.apache.spark.rdd.RDD[(String,Iterable[Int])]
scala>val rdd6=rdd3.groupByKey() //rdd6就变成了Iterable[Int]
[签名]
rdd6:org.apache.spark.rdd.RDD[(String,Iterable[Int])]=ShuffledRDD[10]at groupByKey at<console>:30
scala>rdd6.collect  //rdd6收集,分完组在统计它的个数
[签名]
 //rdd6现在是单词和数字的迭代集合的映射
res11:Array[(String,Iterable[Int])]=Array((world2,CompactBuffer(1)),(world2,CompactBuffer(1,1,1)),(world5,CompactBuffer(1)),(world2,CompactBuffer(1)),)
scala>rdd6.map    //变换
map  mapPartitions   mapPartitionsWithIndex mapValues//mapValues这里是对V变换,key是单词,V就是迭代器其实就是数字。把这些数字加起来就行了。可以不用加因为每个数字都是1,如果元素的个数就是它的总和。
scala>rdd6.mapValues
[签名]
//terable[Int]它是可以迭代的量,从头terable[Int]到=>U(是一个泛型)的映射
def mapValues[U](f:Iterable[Int]=>U):org.apache.spark.rdd.RDD[(String,U)]
scala>rdd6.mapValues(_.size)
scala>val rdd7=rdd6.mapValues(_.size) //这里又变成了RDD[(String,Int)]字符串和整型值对偶
[签名]
rdd7:org.apache.spark.rdd.RDD[(String,Int)]=MapPartitionsRDD[12]at mapValues at<console>:32
scala> rdd7.collect  //通过它去变换,分完组之后它把值聚在一起。然后再对值进行变换
res13:Array[(String,Int)]=Array((world2,1),(world4,1),(hello,1),(world2,1))
一年的最高气温
scala>

RDD1的方法

RDD2的方法

RDD3的方法,多被ByKey,reduce等一些方法,当你一旦变成key对的形式。rdd3就变成了Map.reduceByKey是按key来聚合。虽然很多bykey不是Map。如果是Map的话key就是唯一的,它就是唯一的。用scala来聚合,先得toList.就怕它相同的去重了。所以在Spark里面Map函数变成了一个二元元组的话。只要是二元元组的话,就提供各种ByKey的操作。但这个ByKey不是Map.

reduceByKey是按照key来聚合它的值,严格来说是reduceVuluesByKey。reduceByKey是一个高阶,把两个值变成一个值。再去跟第三个值再聚合。reduceByKey将值累加除掉重复

RDD4的方法

使用spark实现气温

[centos@s101 /home/centos]$cat temp.dat
scala> val rdd1=sc.textFile("file:///home/centos/temp.dat")
scala> rdd1.collect
collect collect
scala>rdd1.collect //rdd1一收集就变成了一行一行的数据
//压扁包含切割部分
scala>val rdd2=rdd1.flatMap(_.split(" "))
scala>rdd2.collect  //这里不是压扁,压扁就是年度和气温值了分开了把它变成一个元组年度是key,气温是V
//map的每一行都抓,先把它切开.切开以后变成了数组,变成数组之后返回的是一个元组(arr(0)就是年度arr(1)就是气温
scala> val rdd2=rdd1.map(line=>{var arr=line.split(" ");(arr(0),arr(1))})
scala>rdd2.collect  //这样一来的话它就,气温和年度都成了字符串,应该把它变成数字(直接toOmt)
scala>val rdd2=rdd1.map(line=>{var arr=line.split(" ");(arr(0).toInt,arr(1).toInt)})
scala>rdd2.collect  //将气温和年度变成Int类型,现在它是二元元组的,就是一个对偶。就是一个map,变换。此时就可以调用reduceByKey
scala>rdd2.reduceByKey //把两个整数聚成一个整数,找历年的最高气温。
// if() 取一个最大值。
scala>val rdd3=rdd2.reduceByKey((a,b)=>if(a>b) a else b)
//还需要排序,按年度排序
scala>val rdd4=rdd3.sortBy
sortBy   sortByKey
//按年度排序,年度就是Key
scala>val rdd4=rdd3.sortByKey
//ascending就是升序的意思numPartitions分区数
def sortByKey(ascending:Boolean,numPartitions:Int):org.apache.spark.rdd.RDD[(Int,Int)]
scala> val rdd4=rdd3.sortByKey(true)//给它一个key按升序排序
scala>rdd4.collect //这样没有显示全
scala> rdd4.foreach(println)
scala> val rdd4=rdd3.sortByKey(false).foreach(println)
//按照气温高低来排序,就不能是sortByKey了。
scala> val rdd4=rdd3.sortBy
scala>val rdd4=rdd3.sortBy
//sortBy如何写  sortBy是泛型K,第一个参数是函数(从一个二元组组员到一个key的映射。并且这个key能比较大小(implicit ctag:scala.reflect.ClassTag[K]):柯里化函数)),第二个参数是升降序ascending:Boolean,第三个是分区numPartitions:Int,整个这个((Int,Int))=>K是一个函数,这个函数它有1个参数,这个参数的类型是二元组
def sortBy[K](f:((Int,Int))=>K,ascending:Boolean,numPartitions:Int)(implicit ord:Ordering[K],implicit ctag:scala.reflect.ClassTag[K]):org.apache.spache.spark.rdd.RDD[(Int,Int)]
scala>val rdd4=rdd3.sortBy
//((a,b)它是一个二元组,第二个组员是气温,它就是取出b。此刻是要降序ascending是升序
scala>val rdd4=rdd3.sortBy((a,b)=>b)
scala>val rdd4=rdd3.sortyBy(t=>t._2,false) //按气温降序  false就是降序
scala>rdd4.collect
scala>rdd.foreach(println)
scala>val rdd4=rdd3.sortBy(t=>{- t_2},true)//让它取反后升序
scala>rdd4.collect //先收一下就变成了一个数组了,不collect一下它就没有做到一个集合。就不是分布式的了。
scala>rdd.foreach(println)
作业
1.聚合气温数据。聚合出max,min,avg

scala>rdd1.collect //rdd1一收集就变成了一行一行的数据如下图

scala>rdd2.collect

scala>rdd2.collect //这样一来的话它就,气温和年度都成了字符串

scala>rdd2.collect //将气温和年度变成Int类型,现在它是二元元组的,就是一个对偶。就是一个map,变换。此时就可以调用reduceByKey

// if() 取一个最大值。

scala>val rdd3=rdd2.reduceByKey((a,b)=>if(a>b) a else b) 这里是按年度排序的,年度是key

scala>rdd4.collect

[Maven]

<dependencies>
   <dependency>
       <groupId>org.apache.hadoop</groupId>
       //这里指的是scala的版本。它依赖于那个
       <artifactId>spark-core_2.11</artifactId>
       //这里是spark自己的版本
       <version>2.1.0</version>
   </dependency>
</dependencies>
//再加一个单元测
<dependencies>
   <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.11</version>
   </dependency>
</dependencies>

[Scala文件]

object WordCOuntScala{
 def mian(args:Array[String]):Uint={
   //创建spark配置对象
   val conf=new SparkConf()
   //给名称//创建的时候先给它一个conf
   conf.setAppName("WCScala")
   //再给它一个Master
   conf.setMaster("local")
   //创建上下文,把conf交给上下文 
   val sc=new SparkContext()  //此时需要参数
   //加载文档
   val rdd1=sc.textFile("file:///d:/mr/word.txt")
   //压扁
   val rdd2=rdd1.flatMap(_.split(" "))
   //标1成对
   val rdd3=rdd2.map((_,1))
   //开始聚合
   val rdd4=rdd3.reduceByKey(_+_)
   val arr=rdd4.collect()  //collect()   Array[(String,Int)]
   //手动打印
   arr.foreach(println)
   
   //链式编程
   sc.textFile("file:///d:/mr/word.txt").flatMap(_.split(" ")).map((_,1)).redyceByKey(_+_).collect().foreach(println)
   println("hello world")
 }
}
sc是shell内置的spark对象上下文的变量。
[SparkContext]
SparkContext(org.apache.spark)
def this()=this(new SparkConf())
//它需要的是Spark的配置SparkConf
class SparkContext(config:SparkConf)extends Logging{}

[Java实现]
在java里面最好带包
com.dzc.spark.mr.WorldCount.Java

package com.zdc.spark.mr

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.function,pairFlatMapFunction;

import java.util.Arrays;
import java.util.Iterator;

public class WordCountJava{
  public static void main(String[] args){
   SparkConf conf=new SparkConf();
   conf.setAppName("wcJava");
   conf.setMaster("local");
   //在scala里面加上java前缀就是java里面的了 Api
   //创建一个上下文对象
   JavaSparkContext sc=new JavaSparkContext(conf);
    //加载文件
   JavaRDD<String> rdd1=sc.textFile(path:"file:///d:/mr/word.txt");  //返回值是   JavaRDD<String>
    //压扁     //只要压扁就可以了
    JavaRDD<String>rdd2=rdd1.flatMap(new FlatMapFunction<String,String>(){
      public Iterator<String>call(String s)throws Exception{
        String[] arr=s.split(regex:" ");
        return Arrays.asList(arr).iterator();
      }
    });
    
    //压扁,注意了是压扁成对PairFlatMapFunciton<String,String,Integer>String这个表示它原来元素的类型,能推断出来   在java 里面高阶函数就变成了PairFlatMapFunciton接口,用匿名内部类对象方式来传 public Iterator<Tuple2<String,Integer>>call(String s)throws Exception这里的String就是这里的一行。  它是一个元组迭代器
    
    //rdd1.flatMap(new PairFlatMapFunciton<String,String,Integer>(){
      //添加未实现的方法
      //public Iterator<Tuple2<String,Integer>>call(String s)throws Exception{
       // String[] arr=s.split(regex:" "); //它的返回值就是数组
        //Arrays.asList(T...a)(java.util)List<T>,它要的是一个迭代器iterator()
        //return Arrays.asList(arr).iterator();//bian chen canshu 返回的是List
     // }
   // });    //这里要的是flatMapToPair(PairFlatMapFunction....JavaPairRDD<K2,V2>)这个映射成对 //flatMapToPair(PairFlatMapFunction....JavaPairRDD<K2,V2>),PairFlatMapFunction这是一个接口,Java是没有高阶函数概念的。scala到处都是传函数。返回函数。在Java里面是以匿名内部类对象的方式来传。
    
    //标1成对
    //mapToPair返回值def mapToPair[K2,V2](f:PairFunction[T,K2,V2]):JavaPairRDd[K2,V2]={def cm:ClassTag[(K2,V2)]=implicitly[ClassTag[(K2,V2)]]new JavaPairRDD(rdd.map[(K2,V2)](f)(cm))(fakeClassTag[K2],fakeClassTag[V2])}
    JavaPairRDD<String,Integer>rdd3=rdd2.mapToPair(new PairFunction<String,String,Interger>(){
      //Tuple2<String,Integer>这个是元组,它要把每一个单词变成一个单词和一的元组
      public Tuple2<String,Integer>call(String s)throws Exception{
        return new Tuple2<String,Integer>(s,_2:1);
      }
    });
    //按照key聚合    reduceByKey(Function2<Integer,Integer,Integer>func) Function2表示有两个参数的函数
    JavaPairRDD<String,Integer>rdd4=rdd3.reduceByKey(new Function2<Integer,Integer,Integer>(){
      public Integer call(Integer v1,Integer v2)throws Exception{
        return v1+v2; //按key聚合,它是不会改变类型的。它两个整数聚成一个整数。它的返回值类型仍然是JavaPairRDD
      }
    });
    //收集  List<Tuple2<String,Integer>>二元组  collect()//List<Tuple2<String,Integer>>
    List<Tuple2<String,Integer>> coll=rdd4.collect();
    //每一个元素都是二元组,单词和个数的一个元组  en  条目就是
    for(Tuple2<String,Integer>t:coll){
       System.out.println(t);
    }
  }
}
//分步实现
val rdd1 = sc.textFile("file:///home/centos/1.txt");
val rdd2 = rdd1.flatMap(line=>{line.split(" ")})
val rdd3 = rdd2.map(word=>{(word , 1)})
val rdd4 = rdd3.reduceByKey((a:Int,b:Int)=>{a + b})
rdd4.collect()

//一步完成(reduceByKey)
sc.textFile("file:///home/centos/1.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).collect()

//一步完成(groupByKey)
sc.textFile("file:///home/centos/1.txt").flatMap(_.split(" ")).map((_,1)).groupByKey().mapValues(_.size).collect()
posted @ 2018-10-11 19:25  Steve--DZC  阅读(630)  评论(0编辑  收藏  举报