元组是一个轻量级集合,这个集合能够存储任意元素java
元组是使用小括号,元素之间使用逗号分隔,元素的类型是任意的数组
若须要访问元组中的元素 [元组名._数字] 数字是从1开始, 有多少个元素,这个1递增多少次安全
例如: 有一个元组,元组中有三个元素多线程
访问每个元素值 --> _1 _2 _3app
元组属于轻量级的集合,数据最多只能存储22个框架
ps:通常元组会代替Map在Spark中使用函数
对偶元组 --> 元组中存储的数据是成对出现的,就将出现第一个值称为key,第二个值的位置称为Valuethis
/** * 元组 */ object TupleDemo { def main(args: Array[String]): Unit = { //这个就是元组的建立 val t = ("sparkcore","sparkSQL","SparkStreaming") //获取值 val value: String = t._1 //建立元组的同时,指定变量存储数据(不推荐) val t1,(a,b,c) = ("sparkcore","sparkSQL","SparkStreaming") // val t1_1 = a //Scala中提供经过tuple元组类来建立 //tuple1是无限大 //剩余的tuple后面的数字表明了最多能够存储多少个元素 //系统给定元组的最大值是22个,超过22就没法存储了,此时建议改成Array或List val tuple = new Tuple1(1.3,14,"你好") val tuple2 = new Tuple2(1.3,14) }
val tuple = new Tuple1(1.3,14,"你好") val tuple2 = new Tuple2(1.3,14) //遍历方式1(迭代器遍历) for(ele <- tuple.productIterator){ println(ele) } //遍历集合 --> foreach 这个方法就是遍历集合使用,没有返回值 //foreach方法是获取集合每个元素并处理, 返回值是一个泛型,因此最终输出什么数据类型由需求决定 /* 方法: def 方法名(参数列表):返回值类型 = { 方法体 } 函数: val 函数名 = (参数列表) => {函数体} */ //先定义一个函数 val pt = (x:Any) =>{println(x)} tuple.productIterator.foreach(pt) //匿名函数 tuple.productIterator.foreach((x:Any) =>{println(x)}) //简化 tuple.productIterator.foreach(x =>println(x)) //只须要一个能够获取数据的变量--> 此时可使用 下划线代替 tuple.productIterator.foreach(println(_)) //由于是打印数据,此时参数是默认(就是遍历集合获取来的,此时Scala容许再次省略下划线) tuple.productIterator.foreach(println)
spa
package Scala_03 /** * 拉链操做 */ object TupleDemo2 { def main(args: Array[String]): Unit = { //zip就是元组的拉链操做,将两个元组中数据进行合并,造成对偶元组 val name = Array("tom","jerry","kitty") val scores = Array(2,3,4) //当前数组中存储的是一个一个的元组对象 //谁调用方法就是就是key,谁作参数传递 谁就是 value val tuples: Array[(String, Int)] = name.zip(scores) println(tuples.toBuffer) //两个存储数据的集合 中的数据不一致 val name_1 = Array("tom","jerry","kitty") val scores_2 = Array(2,3) //ps:若是两个集合数据长度不一致,此时拉链操做谁以最小长度的集合为基准 进行对偶元组合并,多余的部分会删除 val tuples_2: Array[(String, Int)] = name_1.zip(scores_2) println(tuples_2.toBuffer) //zipAll 和zip是相似的,可是若齐总某一个集合集合中的元素缺乏,将使用默认元素填充 val xs = List(1,2,3) val zx = List("一","二","三","四") val tuples_3 = xs.zipAll(zx,0,'_') println(tuples_3) //zipwithIndex 将集合中元素和因此进行结合 val list = List(1,2,3) val tuples_4 = list.zipWithIndex println(tuples_4.toBuffer) //若须要从指定位置开始组合 val tuples_5 = list.zip(Stream from 1) } }
Scala中的集合是分为可变和不可变线程
package Scala_03 /** * list集合 */ object ListDemo { def main(args: Array[String]): Unit = { val empty = List() //空集合 val names = List("xiaobai","xiaohong","xiaohuang") //有值 val moreList = List(List(1,2,3),List(2,3,4))// 集合中存储的数据是另一个集合对象 //运算符 //列表中有一个默认空值 nil 它能够和 :: 中缀符 一块儿使用 构建集合对象 // :: 和 nil一块儿使用 它 是右结合 val str:List[String] = ("小明" :: ("小红" :: ("小黄" :: Nil))) println(str) val s = List("姓名") //将其余集合中数据添加到当前集合汇总 val strs :List[String] = "小明" :: "小红" :: "小黄" :: s println(strs) //使用nil以后会将当前集合先看作是一个总体 nil就至关于建立了集合,因此当前全部数据 都会当前集合中元素进行存储 // s 就会当作一个List集合对象存储到当前集合中 val ss = "小明" :: "小红" :: "小黄" :: s :: Nil println(ss) } }
package Scala_03 object ListDemo2 { def main(args: Array[String]): Unit = { val list = List(1,2,3) //全部不可变list操做都会返回一个全新的List val list2 = 0 :: list // 添加数据 val list3 = 0 +: list //都是向集合的开头添加数据 val list4 = list :+ 4 //向集合的末尾提N家数据 val list5 = list ++ list4 //将两个集合合并 //将某一个集合添加到当前集合的前面 val list6 = list4 ++: list val list6_1 = list4 ::: list //此操做和上面的操做是同样的 } }
package Scala_03 object ListDemo3 { def main(args: Array[String]): Unit = { //遍历集合的方法: /* 1.map遍历集合获取集合中每个元素,并将元素进行处理(自定函数函数),返回一个全新的集合 2.filter遍历集合获取集合每个元素,并将元素进行处理(这个自定义函数返回值必须是Boolean) 而后只有获得true,才会存储到新的集合中 这两个方法一样适用于List */ //3.foreach 这个方法主要做用即便遍历集合并处理集合中数据(自定义函数),这个方法没有返回值 val list = List(1,2,3) val list_1: List[Int] = list.map(_*2) val list_2: List[Int] = list.filter(_>1) list.foreach((x:Int)=>println(x)) list.foreach(x => println(x)) list.foreach(println(_)) list.foreach(println) /* map和foreach的区别 1.map方法存在返回值,处理完数据以后会返回一个新的集合可是foreache是没有返回值的,处理完数据以后时没有返回结果的 2.由于map具备返回值,因此map多用于进行集合中数据处理,而foreach没有返回值,因此多用于打印集合集合中数据 */ //ps:s虽然foreach不具有返回值,可是foreach内部处理函数和Map实际上是同样的,因此foreach也能够对集合中数据操做,操做完成以后多用于输出 //例如 map将集合集合中的元素扩大二倍,foreach也可作到,可是不能返回值出新的集合 list.foreach(x=>println(x*2)) // list.max 最大值 list.min 最小值 //head 返回列表第一个元素 val head: Int = list.head //tail 返回除第一个元素以外的其余元素 val tail: List[Int] = list.tail //concat 将两个集合拼接 至关因而 ++ val list1 = List(4,5,6) val newList: List[Int] = List.concat(list,list1) //反转 val reverse: List[Int] = list.reverse //长度 //list.length list.size //take -> TopN 提取列表前N个数据 --> N就是具体的数值 val topN: List[Int] = list take 1 //拉链 zip zipAll zipwithIndex均可以使用 //list.sorted list.sortwith 均可以使用排序 //丢弃列表前N数据 --> N是具体的值 val ints: List[Int] = list drop 1 } }
package Scala_03 /* 可变ListBuffer */ object ListBufferDemo { def main(args: Array[String]): Unit = { import scala.collection.mutable.ListBuffer val list1 = ListBuffer[Int](1,2,3) val list2 = new ListBuffer[Int] list2 += 4 //追加 list2.append(1) list2 ++= list1 //添加集合 } } 对列表进行拆分 val list = List(1,2,3) val List(a,b,c) = list 此时 a b 和c 就会获取 1,2,3的值
package Scala_03 import scala.collection.immutable.HashSet import scala.collection.mutable /* 不可变和可变 HashSet是排重 Hash表 --> 数组+链表 */ object HashSetDemo { def main(args: Array[String]): Unit = { val set = new HashSet[Int]() val set1: HashSet[Int] = set+1 //添加 val set2 = set1 ++ Set(1,2,3)//合并集合 println(set2) //除了HashSet以外 可使用使用Set val s = Set(1,2,3) import scala.collection.mutable._ val mutableSet = Set(1,2,3)//可变Set val set3 = new mutable.HashSet[Int]() set3 += 2 set3.add(4) //存在则删除,不存在 不会报错不生效 set3 -= 2 set3.remove(2) } }
package Scala_03 /** * 两个Set集合操做 */ object SetDemo2 { def main(args: Array[String]): Unit = { //合并Set集合 val set1 = Set(5,6,9,20,30,45) val set2 = Set(50,60,9,20,35,55) val set = set1 ++ set2 //交集 println(set1.&(set2)) println(set1.intersect(set2)) //并集 println(set1.union(set2)) //差集 println(set1.diff(set2)) //遍历Set val iterator = set1.iterator while(iterator.hasNext){ println(iterator.next) } } }
总结:
Scala中集合:分为可变和不可变
List Set Array Map -->可变和不可变,Array是定长和变长
元组轻量级存储数据的一个集合,最多只能存储22个元素多用因而对偶元组代替Map
在Spark中使用级别: 元组->Array-->List--->Map---->Set
ps:方法主要是以Array和List为主,其他Map和Set可使用个别方法 遍历集合: map 遍历操做数据并返回 filter遍历操做数据并返回 知足Boolean表达式 foreach 遍历操做数据可是没有返回多用于打印 package Scala_03 /** * 经常使用方法 */ object CollectionMethodDemo { def main(args: Array[String]): Unit = { val list = List(List(1,2,3),List(4,5,6)) //要求: 将集合进行处理 并获得 一个 新的集合 List(1,2,3,4,5,6) //压平集合(能够将集合中存储的集合进行扁平化处理) //将集合存储的集合对象进行扁平化处理(将存储在集合对象中集合数据获取出来造成一个新的集合) val flatten: List[Int] = list.flatten println(flatten) val line = List("hello tom hello jerry","hello xiaobai hello") //需求将当前集合中的数据进行处理 -- > List("hello","tom","hello".....) val stringses: List[Array[String]] = line.map(_.split(" ")) stringses.foreach(x=>println(x.toBuffer)) val list_1 = stringses.flatten println(list_1) //Scala中为了应对数据中存在集合套用集合的状况,推出 faltMap --> 就是flatten + Map 遍历的同时并压平 val line_1 = List("hello tom hello jerry","hello xiaobai hello") val strings: List[String] = line_1.flatMap(_.split(" ")) /* flatMap和Map的区别 均可以对数据继续进行遍历处理,.map只是对数据处理并不具有对数据的扁平化处理,flatmap是Flatten+Map结合体,便可以遍历数据也能够对数据进行 扁平化处理,flatMap是Spark中比较经常使用获取数据后的处理方法,其次是Map,可是flatMap是有局限性,在于它会压平数据,不是全部的状况都须要压平. */ //forall 对整个集合中元素进行条件过滤.只有当全部元素都知足的时候,才会返回true 不然就是false val list_2 = List(1,2,3,4,5) val bool: Boolean = list_2.forall( _ < 3) //partition 分区 主要是对集合集合汇总数据进行分区(分组) //scala中体现就是出现不一样集合, 可是在SparkCore中是存在不一样分区中[Sparkcore中体现] val list_3 = List(1,2,3,4,5,6) //这boolean类型表达式决定如何分数据 val tuple: (List[Int], List[Int]) = list_3.partition(_%2 == 0) //fold 和 reduce //fold是一个聚合函数(求和) 须要两个参数 第一个是默认值 第二个参数是计算逻辑 //计算流程: 首先x会先获取0这个初始值,而后y会获取集合第一个元素而后相加 // 以后的每一次计算 x获取的都是上一次计算的结果 即 x = x+y // y值依旧获取集合中剩余的元素进行计算 ,最终中止是是y不能再获取到集合元素时中止 val list_4 = List(1,2,3,4,5) val sum = list_4.fold(0)((x,y) => x+y) //reduce //计算流程 首先x和y会获取集合中第一个或第二个元素的值并进行计算 --> 1+2 = 3 // 以后的每一次计算x获取的是上一次计算的结果即 x = x+y 而y继续获取剩余的集合中的元素参与运算 直到集合中没有元素中止 list_4.reduce((x,y)=>x+y) } } 求和 sum 排序 sorted , sortwith 最大值 max 和 最小值 min
package Scala_03 /* Scala版本 模仿作的 */ object WordCount { def main(args: Array[String]): Unit = { // 读取文件数据存储在集合中 val line = List("hello tom hello jerry","hello xiaobai hello","hello tom") //将集合中的数据进行处理,,获取集合中每一条字符串,将字符串进行拆分获得单词 val words: List[String] = line.flatMap(_.split(" ")) //须要将单词以KV的形式记性拼接 --> (单词,1) --> 明确当前存储类型就是kv键值对 // Scala中提供两种方式 Map 和 元组 --> 推荐使用元组,缘由在于元组擦操做数据更加方便,不会像Map同样须要调用get方法获取数据 val tuples: List[(String, Int)] = words.map((_,1)) //单词和次数已经成为了元组,须要对次数进行累加,问题是不知道哪些单词是一组 // 将相同的单词进行分组 // key 单词 value 原有单词所存在的元组 val grouped: Map[String, List[(String, Int)]] = tuples.groupBy(_._1) //此时已经根据单词进行了分组 相同的单词会汇聚成List集合,经过reduce来进行计算能够相对来讲比较麻烦 val sumed:Map[String,Int] = grouped.mapValues(_.size) //Top1 ,数据已经存在Map集合中,此时进行排序 val list: List[(String, Int)] = sumed.toList //Map转换为List时会将kv键值对以元组的形式存 //这个排序是根据传入的指定值来进行排序的,默认是升序,没法直接降序,Spark中有一个和这个方法同样的sortBy,是能够自由升序降序 val sortedList = list.sortBy(_._2) val reverseList = sortedList.reverse val top1 = reverseList take 1 println(top1) //正常版本 val top2 = line.flatMap(_.split(" ")).map((_,1)).groupBy(_._1).mapValues(_.size).toList.sortBy(_._2).reverse.take(1) } }
缘由:Spark是一个并行计算框架,基于内存,因此会开启多个线程执行程序 Scala中可使用par进行多线程模拟 package Scala_03 /** * 并行化 */ object ParDemo { def main(args: Array[String]): Unit = { /* Spark在编写程序的时候,能够提交集群运行,也能够在本地执行 能够在编写Spark程序的时候 进行本地运行配置setMaster 运行模式设置 须要开启本地运行--> 咱们三种方式 local --> 单线程 local[值] --> 更值来开启对应的线程数,用来模拟spark的平行计算 local[*] --> * 主要表明当前电脑空闲多少线程就使用多少线程来进行模拟计算 */ //用par模拟并行化计算 //1.求和 -->聚合函数 --> sum , fold ,reduce //1.1 sum进行计算 println("--------------------------------sum计算------------------------------------") //ps:sum只能用来求和没法计算其余方式 val arr = List(1,2,3,4,5,6,7,8,9,10) //55 //单线程计算 val sumed = arr.sum println("单线程sum:"+sumed) // 1+2+3+4... //开启平行化处理计算 val sumed2 = arr.par.sum println("多线程sum:"+sumed) //(1+2)+(3+4+5+6)+(7+8+9+10) //总结:不管是在单线程仍是多线程计算求和计算结果都是没有问题 println("--------------------------------sum计算------------------------------------") //reduce 求和 println("--------------------------------reduce计算------------------------------------") //ps:sum只能用来求和没法计算其余方式 val arr_1= List(1,2,3,4,5,6,7,8,9,10) //55 //单线程计算 val sumed3 = arr_1.reduce(_+_) println("单线程reduce:"+sumed3) // 1+2+3+4... //开启平行化处理计算 val sumed3_1 = arr_1.par.reduce(_+_) println("多线程reduce:"+sumed3_1) //(1+2)+(3+4+5+6)+(7+8+9+10) //总结:不管是在单线程仍是多线程计算求和计算结果都是没有问题 //reduce是能够写本身的计算逻辑,既然可使用+ 同理也能够计算 - //单线程计算 val sub = arr_1.reduce(_-_) // 1-2-3-4... println("单线程reduce:"+sub) //开启平行化处理计算 此时不知道有多少个线程在线程在执行(1-2) -(3-4-5) - (9-10) val sub_1 = arr_1.par.reduce(_-_) println("多线程reduce:"+sub_1) //在计算求差值计算时候reduce是没法保证在多线程下计算记过准确 // reduceleft 和 reduceright --> 不管是单线程仍是多线程 ->都是按照一个方向计算计算的 //可使用reduceleft来修正计算计算记过 --> 必须是从左向右计算 val sub_2 = arr_1.par.reduceLeft(_-_) println("多线程reduce:"+sub_2) //在Spark并行计算中若是须要使用计算求差值这样的计算,建议使用 reduceLeft --> reduceRight计算逻辑和left是同样的(从右向左) println("--------------------------------reduce计算------------------------------------") //fold 求和 println("--------------------------------fold计算------------------------------------") //ps:sum只能用来求和没法计算其余方式 val arr_2= List(1,2,3,4,5,6,7,8,9,10) //55 //单线程计算 val sumed4 = arr_2.fold(10)(_+_) println("单线程fold:"+sumed4) // 1+2+3+4... //开启平行化处理计算 val sumed4_1 = arr_2.par.fold(10)(_+_) //fold一旦开启并行化,就会进行屡次的计算--> 当前整个初始值只要进行进行一次线程计算 //就会尽心一次10的相加 --> 例如: 10+1+2 --> 12 10+3+4 println("多线程fold:"+sumed4_1) //总结在平行化的前提下,fold 不建议进行 求和计算,由于会屡次计算初始值,若是须要当前初始值只计算一次 //foldLeft 和 foldRight --> 强制要求计算方式是从左向后 和 从右向左 val sum5 = arr_2.par.foldLeft(10)(_+_) //聚合函数 aggregate 和 fold相似 可是 计数逻辑多 // aggregate(初始值)(局部聚合,全局聚合) --> aggregateByKey(SparkCore中算子) println("--------------------------------fold计算------------------------------------") } }
|
|||||||||||||||
ps:在scala中描述一个事物须要使用class修饰的,在Scala中须要执行代码即执行类须要使用object来修饰
Scala中 object表明的是类的修饰,而Java中Object表明的是超级父类,Scala中的超级父类是Any
package Scala_03 //Scala类中属性 /* 在Scala中类并不须要使用public修饰,由于默认都是共有 在Scala中class修饰的类都是用来描述事物的,在没有指定构造发方法以前,默认是存在一个无参构造方法的 */ class Student { //类中定义属性 /* 由于Scala中对变量的修饰基本上即便var 和 val,这样两种修饰一样适用于属性 定义属性时使用var修饰,那么就至关于属性自带getter和setter 定义属性时使用val修饰,那么就至关于属性自带getter Scala类声明属性,若是使用自动推断,必须显示的进行赋值 不想使用自动推断,此时必须明确表示该数据类型是什么 */ var name = "tom" var age:Int = _ //当前属性并不须要初始值,此时可使用 _ 做为占位符代替初始值 //val修饰属性不可使用_ 占位由于是只读属性 只会被赋值一次,一但使用下划线 就没法在赋新值 // val gender:String= _ //没有明确数据类型,此时不容许使用下划线 //var address = _ // 可使用 私有修饰符 (伴生类能够访问这个私有属性) private var height :Int = 155 //对属性更加严格的权限控制 [this]表明只能当前类访问 伴生类也不能够 private[this] val cardID = "123456" //建立对象 val student = new Student() // val student = Student//这样的建立多用因而伴生类 --> 触发 apply方法 Student必须是一个Object类 }
package Scala_03 /* 自定义getter和setter */ class Ponit { /* 为了保证数据安全,面向对象中封装性 会将属性进行私有化设置 作私有化属性时建议的命名规则 要求以 _ 为前缀, 定义属性的名字 例如 _属性名 getter方法 def 方法名 = 当前属性 --> 方法名是当前属性的名字 setter方法 def 方法名(参数列表):Unit = { 对属性赋值} --> 方法名必须是 属性名_ */ private var _x = 0 //获取这个属性 getter def x = _x //赋值 setter def x_(x:Int):Unit = { _x = x } def showInfos()={ val p = new Ponit() //获取属性 println(p.x) p.x_(10) } }
为了方便从Java程序猿转变为Scala程序猿,方法理解和使用和Java中getter和Setter彻底同样
package Scala_03 import scala.beans.BeanProperty class Person { //在建立属性时候提供getter和setter方法,使用是一个注解 @BeanProperty var name:String = _ } object Person{ def main(args: Array[String]): Unit = { val p = new Person() p.getName p.setName("1") } }
package Scala_03 import java.util import scala.collection.mutable /** * 集合互相转换 */ object ScalaToJava { def main(args: Array[String]): Unit = { import scala.collection.JavaConverters._ //将当前集合转换为Java中的List val javaC: util.List[Int] = List(1,2,3,4).asJava //Java中集合转换为Scala中集合 val scalaC: mutable.Buffer[Int] = javaC.asScala //万能方法 toXXXX -> XX就是你要转换的集合 scalaC.toList } }