您的位置:首页 > 其它

map、flatMap(流的扁平化)、split 的区别

2019-03-13 19:45 751 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zimiao552147572/article/details/88539742

1.flatMap:
    流的扁平化,最终输出的数据类型为一维数组Array[String]。
    被分割出来的每个数据都作为同一个数组中的相同类型的元素,最终全部被分割出来的数据都存储于同一个一维数组中。
    结论:多行数据被分割后都存储到同一个一维数组Array[String]中。
2.map:
    最终输出的数据类型为二维数组Array[Array[String]]。
    以相同分隔符分割出来的数据存储到同一个一维数组Array[String]中,一旦遇到分隔符所无法分割的位置(如遇到回车换行符时)时,
    便创建出一个新的一维数组Array[String],后面所分割的数据则都存储到新的一维数组Array[String]中,
    即分隔符所无法分割的位置作为新建一维数组Array[String]的标志。
    结论:一行数据就为一个一维数组Array[String],多行数据就有多个一维数组,最终多个一维数组一起被封装到同一个一维数组中。
=====================================================


        读取本地文件,实现文件内的单词计数。
        本地文件 /root/scala/words.txt 内容如下:
            hello me
            hello you
            hello her

        sc.textFile("file:///root///scala///words.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).collect
        输出 res0: Array[(String, Int)] = Array((hello,3), (me,1), (you,1), (her,1))
      解析:
        1.flatMap(_.split(" ")):输出数据 Array[String] = Array(hello,me,hello,you,hello,her)
            使用空格作为换行分隔符,被分割出来的每个数据都作为同一个数组中的相同类型的元素,最终全部被分割出来的数据都存储于同一个一维数组中。
            同时还会以回车换行符作为默认的分隔符,即回车换行符前面的数据也会被自动进行分割,而回车换行符后面所分割出来的数据同样存储于同一个一维数组中。
        2.map(_.split(" ")):输出数据 Array[Array[String]] = Array(Array(hello,me),(Array(hello,you),(Array(hello,her))
            使用空格作为换行分隔符,以相同分隔符分割出来的数据存储到同一个一维数组Array[String]中,最终输出的数据类型为二维数组Array[Array[String]]。
            同时还会以回车换行符作为新建一维数组Array[String]的标志,而回车换行符后面所分割的数据则都存储到新的一维数组Array[String]中。
        3.map((_,1)):
            map()首先表示遍历出数组中的每个元素。
            flatMap(_.split(" ")).map((_,1)):遍历出的是每个字符串 hello,me,hello,you,hello,her
            map(_.split(" ")).map((_,1)):遍历出出的是每个Array数组 Array(hello,me),Array(hello,you),Array(hello,her)    
 

=====================================================


val rdd1 = sc.parallelize(Seq(("one two three four five six seven"), ("one two three four five six seven"), ("one two three four five six seven")))
  
rdd1.map(_.split(" ")).collect
/*
res6: Array[Array[String]] = Array(Array(one, two, three, four, five, six, seven),
                                  Array(one, two, three, four, five, six, seven),
                                  Array(one, two, three, four, five, six, seven))
*/
 
rdd1.flatMap(_.split(" ")).collect
/*
res7: Array[String] = Array(one, two, three, four, five, six, seven,
                            one, two, three, four, five, six, seven,
                            one, two, three, four, five, six, seven)
*/
 
 
val rdd2 = sc.parallelize(Seq((1, "one two three four five six seven"), (2, "one two three four five six seven"), (3, "one two three four five six seven")))
 
rdd2.map(x => (x._1, x._2.split(" "))).collect
/*
res14: Array[(Int, Array[String])] = Array((1,Array(one, two, three, four, five, six, seven)),
                                           (2,Array(one, two, three, four, five, six, seven)),
                                           (3,Array(one, two, three, four, five, six, seven)))
*/
 
 
rdd2.map(x => 
{
    val x2 = x._2.split(" ")
    (x._1, x2.toIterable)
}).collect
/*
res4: Array[(Int, Iterable[String])] = Array((1,WrappedArray(one, two, three, four, five, six, seven)),
                                             (2,WrappedArray(one, two, three, four, five, six, seven)),
                                             (3,WrappedArray(one, two, three, four, five, six, seven)))
*/
 
rdd2.map(x => 
        {
        val x2 = x._2.split(" ")
        (x._1, x2.toIterable)
        }).flatMap 
      { x =>    
        val y = x._2
        for (w <- y) yield (x._1, w)
      }.collect
 
/*
res7: Array[(Int, String)] = Array((1,one), (1,two), (1,three), (1,four), (1,five), (1,six), (1,seven),
                                   (2,one), (2,two), (2,three), (2,four), (2,five), (2,six), (2,seven),
                                   (3,one), (3,two), (3,three), (3,four), (3,five), (3,six), (3,seven))
*/

===============================================================================================

scala> val s = "eggs, milk, butter, Coco Puffs" //除第一个单词外的每个单词前面都带有空格
s: String = eggs, milk, butter, Coco Puffs

scala> s.split(",")
res9: Array[String] = Array(eggs, " milk", " butter", " Coco Puffs") //除第一个单词外的每个单词前面都带有空格

scala> val s1 = "eggs,milk,butter, Coco Puffs" //只有最后一个单词的前面带有空格
s1: String = eggs,milk,butter, Coco Puffs

scala> s1.split(",")
res10: Array[String] = Array(eggs, milk, butter, " Coco Puffs")//只有最后一个单词的前面带有空格

scala> val s = "eggs, milk, butter, Coco Puffs"
s: String = eggs, milk, butter, Coco Puffs

scala> s.split(",").map(_.trim)  //trim 去掉“被分割出来的每个字符串前后面的”空格字符
res11: Array[String] = Array(eggs, milk, butter, Coco Puffs)
 
===============================================================================================

//要处理的字符串数据为:"中国|美国|英国"。目的是希望切开得到每个国家("中国","美国","英国"),然而结果却是("中","国","美","国","英","国")
import org.apache.spark.sql.functions._
split(data(field), "|"))  //data是一个Spark DataFrame,其中的field字段是由竖杠|隔开的字符串(如:"中国|美国|英国")

//要处理的字符串数据为:"中国|美国|英国"。而结果正是切开得到每个国家("中国","美国","英国")
import org.apache.spark.sql.functions._
split(data(field), "\\|"))

===============================================================================================

String中的 split(",") 和 split(",",-1) 的区别

1、当准备要被切割处理的字符串的最后一位有值(非分隔符)时,两者没有区别。
2、当准备要被切割处理的字符串的最后一位或者最后N位全部都是分隔符,而并非正常数据时,split(",")不会继续切分,并且不保留为null值,
   而split(",",-1)继续进行切分,并且保留出null值作为被切割出来的数据。


package stringsplit;
public class stringSplit 
{
     public static void main(String[] args) 
     {
          String line = "hello,,world,,,";
          String res1[] = line.split(",");
          String res2[] = line.split(",", -1);
          int i=1;
          for(String r: res1)
              System.out.println(i+++r);
          System.out.println("========================");
          i=1;
          for(String r: res2)
              System.out.println(i+++r);
     }

输出结果是:
1hello
2
3world
========================
1hello
2
3world
4      //保留为null值作为被切割出来的数据
5      //保留为null值作为被切割出来的数据
6      //保留为null值作为被切割出来的数据
 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: