###############
# scala #####
###############
#1、在Windows下安装scala(配置环境变量SLALA_HOME:安装目录 Path:%SCALA_HOME%\bin)
#2、在idea的全局配置里 安装scala 插件(plugin),安装之后要重启
#3、在idea的project structure里的Global Libraries和Libraries添加scala-sdk-2.12.10
#4、 new scala Class,入口选object(scala里没有static,object就相当于static)
#5.scala 2.11和2.12 不兼容
#java VS scala
1、scala 基于java 简化逻辑编码(函数式接口+lambda表达式)
2、java oop不纯粹(基本类型+static),scala一切皆对象
3、scala支持面向函数编程
4、java工程化构建,scala面向差异化小任务(类似于sql)
5、scala不支持接口
//入口方法:引入数据 return this;
//过程处理:处理业务 return this;
//出口方法: 展示结果...return this;
环境
运行于jvm之上而且兼容java
特点:
优雅:一行抵多行
速度快:静态编译
方便融合hadoop生态圈,spark依赖scala
字符串 ""+"" """...\n...""" s"hello${i*j}world" (s:表示要进行变量运算,$:表示引用变量)
返回值 return 最后一行表达式|return
访问修饰符 default friendly default public
默认导入 java.lang.* java.lang.*;scala;scala.Predef;
数据类型 基本类型+引用类型 全部引用类型
static 支持 不支持
范式 opp opp+函数式编程
接口 interface trait
oop 类和对象 单例对象|同一文件中同名(伴生类class+伴生对象object(隐式创建))
方法 ()表示调用 无参()可以缺省
java 内置的4个标椎的函数式接口
Supplier<T> => T get(); 生产者(没有进,只有出)
Consumer<T> =>void accept(T t); 消费者(只进不出)
Function<T,R> =>R apply(T t); 函数(一进一出,两个都是对象,可以用来修改,加密...)
Predicate<T> =>boolean test(T t);预测,过滤(进来对象,出来boolean,通常用于过滤(删除,新增,查询...))
#数据类型(全部都是引用类型:基础引用类型;高级引用类型)
数据类型 描述
Byte 8位有符号补码整数。数值区间为-128 到127
short 16位有符号补码整数。数值区间为-32768 到32767
Int 32位有符号补码整数。数值区间为-2147483648 到 2147483647
Long 64位有符号补码整数。数值区间为 -9223372036854775808到 9223372036854775807
Float 32位,IEEE 754 标准的单精度浮点数
Double 64位工EEE 754 标准的双精度浮点数
Char 16位无符号Unicode字符,区间值为U+0000到U+FFFF
string 字符序列
Boolean true或false
Anyval 所有基础类型的父类
Unit 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()
Null null或空引用,不兼容值类型
Nothing Nothing类型在Scala的类层级的最底端;它是任何其他类型的子类型。
Any 是所有其他类的超类
AnyRef AnyRef类是Scala里所有引用类(reference class)的基类
Tuple1~22 (1,...,22)最多22个允许不同类型元素的 (元组)
//var t1 = ("henry","pola","arial")
println(t1._2) 使用元组
Tuple1~32 元组的使用
//语法糖(去掉Tuplen)
var tp:Tuple2[Int,Int] =(1,2) => var tp:(Int,Int) =(1,2)
//提取元组的元素
var tpn:(T,T,...)=(v1,v2,...,vn)
val t:T =tpn._n
//对元组元素集中处理用迭代器(遍历)
val it:Iterator[Any]=tpn.productIterator //【Any】元组迭代时注意类型转换
val arr: Array[Int] = it.asInstanceOf[Array[Int]] //scala:强制类型转换
例:1
var tp:(Int,Int) =(1,2)
tp.productIterator.foreach(println)//使用迭代器遍历元素
tp.productIterator.map(_.toString.toInt*2).foreach(println)//对元组里元素类型进行转换,输出
val swap: (Int, Int) = tp.swap //对二元组两个元素交换位置
swap.productIterator.foreach(println)
例:2
val array:Array[Int] = Array(1,2,3,4,5,6,7,8,9)
val t2: (Array[Int], Array[Int]) = array.partition(_ % 2 == 0)
t2.productIterator.foreach(it=>{ //productIterator:元组类型的迭代器
val arr: Array[Int] = it.asInstanceOf[Array[Int]] //强制类型转换
println(".................")
arr.foreach(println)
})
不指定类型
var 变量 = 值
val 常量 = 值
值类型决定变量类型
(自适应类型:自动感知)
(第一次赋值后类型确定)
声明时必须初始化
变(常)量.getClass.getName
指定类型
var|val 变量:类型 = 值
#变量
弱类型: 第一次复制决定变量类型,之后不可更改(自适应类型:自动感知)
声明规则:声明的同时赋值
var v = VALUE //var s:Int = 10 println(v.getClass.getName)
String TypeName=v.getClass.getName
#声明时指定类型
var V:Type=v.getClass.getName
#特殊变量
_ 表示一个变量的占位符,无需被处理,不可传递,不可封装
面向函数,一个参数可以使用一个_,两个参数可以使用两个_,依次类推
#常量
val v = VALUE
#类型转换
var v:Xxx = v.toXxx
#控制台输出
print[ln] {内容}
#控制台输入(流的重定向)
val reader = new BufferedReader(new InputStreamReader(System.in))
String value = reader.readerLine()
//添加必要的验证
if(条件)
{
var v:Xxx = value.toXxx
}
}
#运算符
算数:不支持 ++|--
关系:同java
逻辑:同java
赋值:=
不支持三目运算符:由分支取代 var v - if(条件) v1 else v2
//var g =0
var gen =if(g==0) 'f' else 'm'
print(gen)
#逻辑(分支,循环)(if和java一样,switch case 不一样)
#分支:
if
值守卫
if守卫
模式守卫
类型守卫(多态)
构造守卫
#值守卫
var g =1
var gen = g match {
case 1 =>'m'
case 0 =>'f'
case _ => 'U'
}
print(gen)
#if守卫
var score = 88
var level = score match {
case x if(x>=90)=>'A'
case x if(x>=80)=>'B'
case x if(x>=70)=>'C'
case x if(x>=60)=>'D'
case _ =>'E'
}
print(level)
//模式守卫(至少一个分组)(用于识别判定 )(.r表示正则 ,至少一个分组,()表示分组)
val rPhone = "(1[3-9]\\d{9})".r
val rPid = "(\\d{17}[0-9X])".r
val rMail = "\\w{3,}@[0-9a-z]{2,}\\.(com|com\\.cn|cn|edu|org)".r
var str = "13789900299"
// var str ="123456789012345678"
// var str = "abc@bb.com.cn"
var t = str match {
case rPhone(p)=>"phone"
case rPid(p)=>"pid"
case rMail(p)=>"mail"
case _=>"UNKNOWN"
}
print(t)
//模式守卫(用于分组提取)
val r2 ="(.*?),(.*?)".r
val r3 ="(.*?);(.*?);(.*?)".r
var str = "beauty;money;power" //通过符号识别判断
var t:Array[String]= str match {
case r2(a,b)=>Array(a,b)
case r3(a,b,c)=>Array(a,b,c)
case _=>Array()
}
//scala中函数名称可以作为引用传递,加()表示调函数,不加表示传函数
t.foreach(println)
#OOP
类型守卫(多态)
var a:AnyVal =11.22
var t= a match {
case _:Int=>"int"
case _:Double=>"double"
case _=>"Exception"
}
println(t)
构造守卫
#循环
(for循环可以配合if使用,还可以配合yield使用,可以赋值)
for(i<-begin to|until end by step; if...)(左边界是闭合的,to可以到右边界,until不可以到右边界)
var v = for(i<begin to|until end by step; if...)yield i
for(i<-1 to 10 by 2){
println(i)
}
for(i<-1 to 10 ;if i>5 && i<8){
println(i)
}
for(i<-1 until 10 ){
println(i)
}
var t =for(i<-1 to 20 ;if i%3==0) yield i //把i值付给t
t.foreach(println)
for(i<-1 to 20 ;if i%3==0) {
println(i)
}
#break和continue
import scala.util.control.Breaks._
breakable(
for(){
if(){
break
}
}
)
//例:
import scala.util.control.Breaks._
breakable(
for(i<-1 to 9 ){
print(i)
if(i>5){
break
}
}
)
import scala.util.control.Breaks
val loop =new Breaks
loop.breakable(
for(i<-1 to 9 ){
print(i)
if(i>5){
loop.break
}
}
)
import scala.util.control.Breaks.
val loop =new Breaks
loop.breakable(
for(){
if(){
loop.break
}
}
)
//例:
#高级特性
#工具类
数值区间 java: BigDecimal
//设置容量:MathContext.DECIMAL[32~128]|UNLIMITED
BigDecimal num = new BigDecimal(12.345678, MathContext.DECIMAL32);
//保留精度
double v = num.setScale(precision, RoundingMode.UP).doubleValue();
//UP 绝对值最大取整
//DOWN 绝对值最小取整(大于0,向下取整;小于0,向上取整)
//CEILING向上取整
//FLOOR向下取整
//HALF_UP四舍五入
//HALF_DOWN四舍五入(*注意5后面还有数(非空),才能入,否则舍去)
//HALF_EVEN 财务舍入法 四舍六入五考虑,五后非零(非空)就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一
double v = num.setScale(2, RoundingMode.HALF_EVEN).doubleValue();//保留两位小数
#java :java.util.Optional<T> 工具类 (Optional 可以作为方法的返回值)
Optional<Integer> opt = Optional.ofNullable(null); //Optional.empty();
if(opt.isPresent()){
System.out.println(opt.get());
}else{
System.out.println("EMPTY");
}
#scala:Option[T]
Option[T] =>Some[T]
=>None
val opt:Option[T]=Some(T t) opt.isEmpty=false val t:T =opt.get
val opt:Option[T]=None opt.isEmpty=true
val v :Option[Int]= f(2)
if(v.isEmpty){
println("NOTHING")
}else{
None
}
例:
val f =(a:Int)=>{
if(a>=0 && a<array.size){
Some(array(a))
}else{
None
}
}//返回Option类型对象
val v :Option[Int]= f(2)
if(v.isEmpty){
println("NOTHING")
}else{
println(v.get)
}
scala:Random:伴生对象(类似于静态的对象)
val randNum= Random.nextInt(bound)
...
字符串
日期
SimpledateFormat sdf= new SimpledateFormat
Date date = new Date([int millisecs]);//获取系统当前时间
boolean yes = date.before(Date d);
boolean yes = date.after(Date d);
Calendar c = Calendar.getInstance(Locale.CHINESE);
c.setTime(Date date);// c.set(2019,8,24);
Date date= c.getTime();
c.add(int field,int value);//c.add(Calendar.YEAR,5);
正则
String string="...";
Pattern p = Pattern.compile("REGEX_STRING");
Matcher m = p.matcher(string);
boolean matched = m.matches();//string 是否和正则匹配
boolean found = m.find();//string 是否包含至少一处正则匹配
boolean found = m.find(position);//string 从指定位置开始是否包含至少一处正则匹配
position = m.end();//锁定结束位置,作为下一次开始位置
json scala 解析json jQuery
<dependency>
<groupId>net.minidev</groupId>
<artifactId>json-smart</artifactId>
<version>2.4.7</version>
</dependency>
val str2 = "{\"name\":\"jeemy\",\"age\":25,\"phone\":\"1501469230058\"}"
//构建json工具对象
val parser=new JSONParser(JSONParser.BIG_DIGIT_UNRESTRICATED)
//简单对象解析
val jo=parser.parse(str2,classOf[JSONObject])
val name=jo.getAsString("name")
val age=jo.getAsNumber("age")
val phone=jo.getAsString("phone")
println(s"$name,$age,$phone")
//解析数组
val array: JASONArray =parser.parse(str.classOf[JSONArray])
array.forEach(obj=>{
val o=obj.asInstanceOf[JSONObject]
println(s"${o.getAsString("subject")},${o.getAsNumber("score")}")
})
URL解析工具类
#函数|方法
函数不写返回类型(由结果决定返回类型),方法写返回类型
//函数定义
val func = {参数列表} =>[{函数体}]
//方法定义(有返回类型)
def method(参数列表):返回类型 =[{方法体}]
//偏函数(关注部分数据的函数)
val partialFunction:PartialFunction[I,R] ={参数列表}=>[{函数体}]
//模式匹配,要满足所有的情况,缺失会报错
//偏函数只要考虑想要的情况
val p:PartialFunction[Int,Int]=(a:Int)=> a match {
case x if(x%2==0)=> x
} //面向数组
array.collect(p).foreach(println)
//函数式编程:【将函数|方法作为参数传递】
(方法不加(),传递的是函数的引用,方法加(),是调用函数,传递的是方法的值)
val func = (a:Any,b:any,f:(参数列表)=>返回类型)
println(test(2,3,add))//提前定义好add函数
println(test(2,3,(a,b)=>a+b))//匿名函数,直接写函数,和上面效果等同
//函数式编程:组合函数:只支持一个参数的多个函数,且函数依次的返回值和参数要兼容
val f1 =...,f2=...
val f=f1 andThen f2 =>f2(f1(...))
val f=f1 compose f2 =>f1(f2(...))
//函数作为参数传递
val f1 =(a:Int)=>a*a
val f2 =(a:Int)=>a+2
val f:Int => Int = f1 andThen f2 //(先计算前面的,结果作为参数传递给后面)
val f:Int => Int = f1 compose f2 //(先计算后面的,结果作为参数传递给前面)
println(f(3))
//函数式编程:将函数作为返回值
val f=()=>{
...
{参数列表}=>{
...
}
}
f(...)(...)
val f=()=>{
val arr:Array[Int] =Array(3,5,1,7,9)
(a:Int)=>arr.applyOrElse(a,(i:Int)=>s"Index out of bounds : $i")
}
//柯里化
val value: Any = f()(8)
println(value)
val f1=(a:Int)=>{
val arr:Array[Int] =Array(3,5,1,7,9)
()=>arr.applyOrElse(a,(i:Int)=>s"Index out of bounds : $i")
}
//柯里化
val value: Any = f1(1)()
println(value)
val f2=(a:Int)=>{
val arr:Array[Int] =new Array(a)
for(i<-0 until arr.size){
arr(i) =1+ Random.nextInt(20)
}
println(arr.mkString(","))
(b:Int)=>arr.applyOrElse(b,(i:Int)=>s"Index out of bounds : $i")
}
//柯里化
val value: Any = f2(5)(4)
println(value)
#集合
#算子(函数|方法)Array
val array =Array(...)
//提取21+1
array.foreach(consumer:(T)=>Unit) //遍历所有元素
val t:T = array(index:Int) //根据下标提取元素 存在下标越界异常 println(array(0))
val t:T= array.apply(index:Int) //根据下标提取元素,存在下标越界异常 println(array.apply(1))
val t:T= array.applyOrElse(index:Int,d:(a:Int)=>Any) //根据下标提取元素,若下标越界,默认返回参数2函数的返回值(也可以根据Map的key获取value)
val t:T= array.head //提取头元素,空数据报NoSuchElementException异常
val t:T= array.last //提取尾元素,空数据报NoSuchElementException异常
val opt:Option[T]= array.headOption //提取头元素,配合isEmpty判定,安全提取
val opt:Option[T]= array.lastOption //提取尾元素,配合isEmpty判定,安全提取
val sub:Array[T] = array.take(count:Int)//从从左侧提取count个元素
val sub:Array[T] = array.takeRight(count:Int)//从从右侧提取count个元素
val sub:Array[T] = array.takeWhile(predicate:(T)=>Boolean)//从从左侧提取满足predicate条件的元素
//从下标0开始提取,若第一个元素不满足,返回空数组;否则从左边第一个满足元素开始,到第一个不满足元素结束
val sub:Array[T] =array.filter(predicate:(T)=>Boolean).foreach(println) //提取所有满足参数函数条件的元素
val sub:Array[T] =array.filterNot(predicate:(T)=>Boolean).foreach(println) //提取所有不满足参数函数条件的元素
val sub:Array[T] =array.collect(pf:PartialFunction[T,R])//提取所有满足参数函数条件(偏函数)的元素(过滤处理,比filter性能高)
val opt:Option[T] =array.collectFirst(pf:PartialFunction[T,R])//提取集合中第一个满足参数函数条件的Option【元素】
val opt:Option[T]= =array.find(f:(T)=>Boolean) //提取左边第一个满足参数函数条件的元素(处理,性能没有collectFirst高)
val sub:Array[T] =array.slice(from:Int,until:Int) //提取下标从from到until之间的元素(左闭右开)
val sub:Array[T]=array.init //提取排除最后一个元素之外的所有元素
val it:Iterator<Array[T]>=array.inits //递归依次提取排除最后一个元素之外的所有元素
val sub:Array[T]=array.tail //提取排除第一个元素之外的所有元素
val it:Iterator<Array[T]>=array.tails //递归依次提取排除第一个元素之外的所有元素
val f:(ix:Int)=>Option[T] =array.lift //获取以下标为参数提取Option数组元素的函数 (函数既可以作为参数,也可以作为返回值)
#修改12
array.update(ix:Int,t:T) //修改原数组指定下标位置的元素值(无返回值,元数组改变)*
valnewarr:Array[T]=array.updated(ix:Int,t:T)//修改数组指定下标位置的元素值,冰女返回修改后的数组(元数组不变)
val uArr:Array[T] = array1 ++ array2 //并集(和union一样)
val uArr:Array[T] = array1 union array2//并集(重复的部分存在两次)
val uArr:Array[T] = array1 intersect array2//交集
val uArr:Array[T] = array1 diff array2 //差集(前者相对于后者的差集)
val uArr:array[T]= array :+ t //尾部追加
val uArr:array[T]= t +: array //头部追加
val uArr:array[T]= array.drop(count:Int) //返回删除左侧count个元素的副本(返回新数组,元数组不变)
val uArr:array[T]= array.dropRight(count:Int)//返回删除右侧count个元素的副本
val uArr:array[T]= array.dropWhile(f:T=>Boolean )//返回删除从左侧开始符合参数函数条件元素的副本,若左一不满足不删除
val uArr:array[T]= array.patch(from:Int,seq:GenSeq[T],count:Int) //将从from开始的count个元素替换为seq;如若seq为空,则删除(删除+插入)
//逐个处理(迭代)(很重要)5
val uArr:array[T]= array.map(f:T=>U) //正向迭代处理
val uArr:array[T]= array.transform(f:T=>U)//正向迭代处理
val uArr:array[T]= array.reverseMap(f:T=>U)//反向迭代处理 reverse+map
val uArr:array[T]= 2DArr.flatten //(扁平化,面向多维数组)降一个维度
val uArr:array[T]= 2DArr.flatMap(f:Array[T]=>U)//(flatMap=flatten.map)降一个维度并处理
//分段|组(重要)5
val parArr:ParArray[T] =array.par//并行数组(提供并行处理机制,开启线程处理,用来提速)
val tp2:(Array[T],Array[T])=array.partition(f:T=>Boolean)//(分区,多元祖)按参数函数条件分为两个(或多个)数组并封装成二元组(多元祖)返回
val tp2:(Array[T],Array[T])=array.span(f:T=>Boolean)//(封装成二元组返回),满足的元素组成的数组和不满足条件的元素组成的数组组成一个二元组
//从下标0开始提取,若第一个元素不满足,返回(空集,全集)组成的二元组,否则第一组从左边第一个满足元素开始,到第一个不满足元素结束,剩余第二组
val tp2:(Array[T],Array[T])=array.splitAt(ix:Int)//以参数下标为界,将集合一分为二,被封装成二元组返回
val it:Iterator[Array[T]]= array.grouped(size:Int) //(分组,为了并行处理)按指定每组元素数量分组(this.length/size).ceiling
val it:Iterator[Array[T]]= array.sliding(size:Int,step:Int)//滑动分组(每组size个元素,每次步进step步,step默认为1)(Map滑动分组,键键合并,值和值合并)
val map:Map(K,Array[T])= array.groupBy(key:K) //指定键分组(T:为多元祖|样例类)(会导致数据倾斜)
//聚合18
val rst:T =array.reduce(f:(T,T)=>T) //对数组从左向右执行参数函数运算(不带初值)
val rst:T =array.reduceOption(f:(T,T)=>T) //等同于reduce,防UnsupportedOperationException,结果包装成Option
val rst:T =array.reduceLeft(f:(T,T)=>T)//等同于reduce
val rst:T =array.reduceLeftOption(f:(T,T)=>T)//等同于reduce,防UnsupportedOperationException,结果包装成Option
val rst:T =array.reduceRight(f:(T,T)=>T)//对数组从右向左执行参数函数运算
val rst:T =array.reduceRightOption(f:(T,T)=>T)//等同于reduceRight,防UnsupportedOperationException,结果包装成Option
//↑(第一次拿前两个元素计算,第二次开始拿上一次的结果和当前元素计算)
//⬇(第一次拿t和第一个元素计算,第二次开始拿上一次的结果和当前元素计算)
val rst:T =array.fold(t:T)(f:(T,T)=>T) //左折叠(最终结果)(带初值)
val rst:T =array.foldRight(t:T)(f:(T,T)=>T) //右折叠(最终结果)
val rst:Array[T] =array.scan(t:T)(f:(T,T)=>T)//左折叠(将过程结果封装成数组返回)
val rst:Array[T]=array.scanLeft(t:T)(f:(T,T)=>T)//左折叠(将过程结果封装成数组返回)
val rst:Array[T]=array.scanRight(t:T)(f:(T,T)=>T)//右折叠(将过程结果分装成数组返回)(结果逆序)
val rst:T =array.par.aggregate(s:()=>T)(map:(T,T)=>T,red:(T,T)=>T)//并行序列并行计算
val t:T = array.sum //累加和
val t:T = array.count(f:(T)=>Boolean) //统计符合参数函数条件的元素数量
val t:T = array.max //最大值
val t:T = array.min //最小值
val t:T = array.maxBy(f:(T)=>Boolean) //满足参数函数条件的第一个值
val t:T = array.minBy(f:(T)=>Boolean)//不满足参数函数条件的第一个值
//验证9+1
val rst:Boolean= array.isEmpty //是否为空
val rst:Boolean= array.nonEmpty //是否不为空
//val rst:Boolean= array.exists(p:Int=>Boolean) //是否存在符合参数函数条件的元素(可以使用count达到类似效果)
val rst:Boolean= array.contains(ele:T) //是否包含参数元素
val rst:Boolean= array.containsSlice(seq:GenSeq)//是否包含子序列(空序列,顺序相同的所有子序列元素)println(array.containsSlice(GenSeq(1,2,3)))
val rst:Boolean= array.forall(f:(T)=>Boolean) //是否所有元素都满足参数函数的条件
val rst:Boolean= array.corresponds(sub:GenSeq[B])(f:(Int,B)=>Boolean) //是否arrayhe和sub同索引元素都满足参数函数条件(array.size= sub.size)
val rst:Boolean= array.sameElements(seq:GenSeq[T])//array和sub是否完全相同(数值,顺序一致)
val rst:Boolean= array.startsWith(seq:GenSeq[T])//array是否以seq开头
val rst:Boolean= array.endsWith(seq:GenSeq[T])//array是否以seq结尾
//大小5
val len:Int = array.size //获取元素数量
val len:Int = array.length //同size
val len:Int = array.prefixLength(f:(T)=>Boolean)//获取左侧(从下标0开始)连续满足参数函数条件的元素数量,否则返回0
//等同于array.segmentLength(f:(T)=>Boolean,0)
val len:Int = array.segmentLength(f:(T)=>Boolean,pos:Int)//获取从pos开始连续满足参数函数条件的元素数量,否则返回0
val len:Int = array.lengthCompare(len:Int) //获取(array.size-len)的差值
//转变19+1(to...自动创建)
//(事先要创建sub数组)
array.copyToArray(sub:Array[T],start:Int,len:Int) //将array从0开始复制len个元素到数组sub的start开始
array.copyToArray(sub:Array[T],start:Int) //array.copyToArray(sub,start,Math.min(sub.length-start,array.size))
array.copyToArray(sub:Array[T]) //array.copyToArray(sub,0,Math.min(sub.length,array.size))
array.copyToBuffer(sub:ArrayBuffer[T]) //将array中所有元素复制到sub中(ArrayBuffer可变集合)
var arr:Array[T]= array.toArray //获取当前数组的引用:等同于arr=array(还是原数组)
var buffer:Buffer[T]= array.toBuffer //获取arrayBuffer类型的拷贝(重新创建数组)**
var set:Set[T]=array.toSet //获取Set类型拷贝(自带去重,无序)*
vararr:Array[T]= arr.distinct //去重*
var arr:Array[T] = array.clone //浅克隆(引用)
var arr:Array[T] = array.repr //等同于clone
var arr:Array[T] = array.deep //深克隆(把元素都克隆,返回类型IndexedSeq[Any])
var arr:Map[K,V]= array.toMap //获取Map的拷贝(一般array元素类型为二元组(二元组转化为map),其他类型会涉及到隐式参数)*
val stream:Stream[T] =array.toStream //获取流对象,懒加载
//var arr:Array[T] = array.padTo(len:Int,elem:T)/如果arr.size<len,则将多余的长度填充参数2(elem)
val arr2d:Array[Array[T]]=arr2d.transpose //二维数组转置(行转列,列转行)
val newArr:Array[(T,B)]=array1.zip(array2:GenIteralbe) //两个数组同下标组合成二元组,并将所有二元组封装成数组返回
val newArr:Array[(T,B)]=array1.zipAll(array2:GenIteralbe,thisEle:T,thatEle:B) //两个数组同下标组合成二元组,并将所有二元组封装成数组返回(数据补全)
//(array1缺失,用thisEle补全;array2缺失用thatEle补全)
val newArr:Array[(T,Int)]=array.zipWithIndex //将元素和下标包装成二元组,并将所有二元组分装成数组返回(元素在前,下标在后)
val tp2:( Array[T],Array[B])=tp2arr.uzip //(拆)按二元组组成的数组拆成的两个数组并封装成二元组返回
val tp3:(Array[T],Array[B],Array[C])=tp3arr.uzip3 //按三元组组成的数组拆成的三个数组并封装成三元组返回
//(多元祖组成的数组可以通过map操作,得的想要的多元组)
//顺序(排序)5
//数组和迭代器进行遍历的区别:迭代器是一次性的,数组是可以多次的
val arr:Array[T]= array.reverse//逆序array(翻转)
val arr:Iterator[T]= arr.reverseIterator//逆序迭代器
val ascArr:Array[T]= array.sorted //排序
//配合隐式参数可将默认升序排序方式改为降序排序( implicit val DESC= Ordering[Int].reverse //隐式参数)
//隐式参数(类型匹配,自动调用(所以要精准匹配,类型最小化,严格控制数量))
val sortedArr:Array[T]= array.sortBy(a:T=>T) //排序(a=a升序,a=-a降序)
val sortedArr:Array[T]= array.sortWith(f:(T,T)=>Boolean)//排序(a<b 升序,a>b降序)
//字符串拼接2
val str:String = array.mkString(sep:String) //以参数指定的分隔符拼接
val str:String= array.mkString(start:String,sep:String,end:String)//以参数指定的分隔符拼接
//查找9
val index:Int= array.indexWhere(p:T=>Boolean) //左起查找第一个满足参数函数条件元素的下标,无返回-1;
val index:Int= array.indexWhere(p:T=>Boolean,start:Int) //左(下标start包含)起查找第一个满足参数函数条件元素的下标,无返回-1;
val index:Int= array.indexOfSlice(seq:GenSeq) //左起查找第一个完全匹配参数序列的首元素下标,无返回-1
val index:Int= array.indexOfSlice(p:T=>Boolean,start:Int) /左(下标start包含)起查找第一个完全匹配参数序列的首元素下标,无返回-1
val index:Int= array.lastIndexWhere(p:T=>Boolean) //右起查找第一个满足参数函数条件元素的下标,无返回-1;
val index:Int= array.lastIndexWhere(p:T=>Boolean.start:Int) //右(start包含)起查找第一个满足参数函数条件元素的下标,无返回-1;
val index:Int= array.lastIndexOfSlice(seq:GenSeq) //右起查找第一个完全匹配参数序列的首元素下标,无返回-1
val index:Int= array.lastIndexOfSlice(p:T=>Boolean.start:Int) //右(start包含)起查找第一个完全匹配参数序列的首元素下标,无返回-1
val ixRng:Rang= array.indicies //获取数组的下标【区间】
###################################################################################
默写:hive所有函数 本周四:2月17日
默写:scala Array函数 本周五:2月18日
hive:udf,udaf,udtf
hive:数据倾斜:下周一:2月21日集中提问(what is skew,why skew,why to deal ,how to deal )
数仓:架构设计,模型构建
######################################################################################
implicit val DESC= Ordering[Int].reverse //隐式参数(类型匹配,自动调用(所以要精准匹配,类型最小化,严格控制数量))
array.sorted.foreach(println)
#oop
访问修饰符
slala:public(默认) protected private
伴生类|半生对象
//方法的参数可以通过等于号设置默认值
//scala方法或函数最后一句话就是返回值,根据最后一句话的特征自动识别
//方法可以指定返回类型,函数自动识别
方法:def method(参数列表):返回类型={方法体}
函数: val func = (参数列表)=>(函数体)
调用方法或函数:
//调用方法或函数时,有默认值的参数可以不传参,运行时自动导入默认值
//调用方法或函数时,可以通过指定参数名的方式(gender='女'),调整顺序
scala的方法中(不管是构造方法还是自定义方法)的参数是可以通过=设定默认值
类的定义:
#一个文件中只有一个类,则称之为类
//主构造器,全参(scala中类的属性和参数不能同名)
class Student(name:String,age:Int=18,gender:Char='男') {
private var _name:String=name
private var _age:Int=age
private var _gender:Char= gender
//辅助构造器(通过this调用主构造器)(通常不写:通过给主构造器的参数设定默认值)
//def this(name:String){
this._name=name
}
//setter
def setName(name:String):Unit = this._name=name
def setAge(age:Int):Unit = this._age=age
def setGender(gender:Char):Unit=this._gender=gender
//getter
def getName:String=this._name
def getAge:Int= this._age
def getGender:Char=this._gender
//单根继承(可以重写默认的父类方法)
override def toString: String =
}
#同一个文件中存在同名的类和对象,则称类为伴生类,对象为伴生对象
伴生对象起补充作用(弥足scala不支持static);伴生对象里面可以藏一些东西
(伴生对象 :scala不支持static,伴生对象里的属性一般为常量(类似静态的),可以通过【伴生对象.属性】调用;像java里的单例对象)
apply(模板方法)在伴生对象中调用伴生类的主构造方法
//(因此通过主构造器创建对象,就不用new了) val henry=Person("pola",18,'女')
//伴生对象 :scala不支持static,单例对象
object Person{
def apply(name: String, age: Int, gender: Char): Person = new Person(name, age, gender)
//一般为常量
val MAN='男'
val WOMEN='女'
//伴生对象可以直接访问伴生类中的私有属性
def getName(stu:Person):String =stu._name
}
object Test {
def main(args: Array[String]): Unit = {
// val henry = new Person(name="henry",18,'男')
//val henry = new Person("pola",17)
val henry=Person("pola",18,'女')
println(henry.getName)
println(Person.getName(henry))
}
}
样例类
case class Tag(userId:Int,movieId:Int,yag:String,timestamp:Long){
override def toString: String = s"$userId,$movieId,$tag,$timestamp"
}
封装
继承:单继承
//继承(属性,构造器(主,辅),方法)
class Student(name:String, age:Int, gender:Char,stuNo:Int,produce:String)
extends Person(name:String, age:Int, gender:Char) {
private var _stuNo:Int=stuNo
private var _product=produce
def setStuNo(stuNo:Int):Unit=this._stuNo=stuNo
def setProduct(produce:String):Unit=this._product=produce
def getStuNo:Int=this._stuNo
def getProduct:String=this._product
override def toString:String=s"${super.toString},${this.stuNo},${this.produce}"
}
样例类
避免被众多下划线困扰(在main方法里面,外面都可以写)
普通类可以继承样例类,可以追加属性
样例类之间可以互相继承(继承的属性需要重写),可以追加属性
case class Tag(userId:Int,movieId:Int,tag:String,timestamp:Long){
override def toString: String = s"$userId,$movieId,$tag,$timestamp"
}
case class Tag2(override val userId:Int, override val movieId:Int, override val tag:String, override val timestamp:Long,age:Int)
extends Tag(userId:Int,movieId:Int,tag:String,timestamp:Long)
class TagInfo(userId:Int,movieId:Int,tag:String,timestamp:Long,age:Int)
extends Tag(userId:Int,movieId:Int,tag:String,timestamp:Long){
private var _age:Int=age
}
特质 trait(相当于java的interface)(里面方法是抽象方法)
单继承(inherit<extends>),多混入(mix<with>)
第一个特质可以extends,第二个开始用with
trait Go {
def show:Unit
}
trait Info {
def self:Unit
}
trait Info {
def self:Unit
}
class Teacher(name:String, age:Int, gender:Char) extends Person(name:String, age:Int, gender:Char) with Task {
override def job(): Unit = ???
override def self: Unit = ???
override def show: Unit = ???
}
======================================
trait Info extends Go {
def self:Unit
}
trait Task extends Info {
def job():Unit
}
class Teacher(name:String, age:Int, gender:Char) extends Person(name:String, age:Int, gender:Char) with Task {
override def job(): Unit = ???
override def self: Unit = ???
override def show: Unit = ???
}
对象可以动态混入特质
val zs = new Student("张三", 22, '男',123,"大数据") with Task {
override def job(): Unit = ???
override def self: Unit = ???
override def show: Unit = ???
}
函数
柯里化:一个多参转化为多个一参
高阶函数:以函数为参数或返回值
闭包:方法内访问方法外的变量
隐式
变量
参数:隐式传入
def method(...) (implicit param:T=INIT_VALUE)
implicit val param:T= VALUE
method(...)
函数(置于伴生对象中):隐式类型转换
class A{
def showA...
}
class B{}
object B{
implicit def toA(b:B):A=>new A(...)
}
def +main{
val b = new B
b.showA
}
隐式类(内部类):唯一参数构造器
异常:
Exception
RuntimeExcepotion=>...
NullPointException
ArithmeticException
InputMisMatchException
ArrayIndexOutOfBoundsException
...
SqlException
IOException
FileNotFoundException
InvalidArguementException
InvalidInvocationException
InterruptedException
Error:无可救药 物理问题(
网络中断
内存不够(OutOfmemory Error|StackOverflow)
)
运行时异常
必须用程序逻辑
编译异常
包的定义
package cn.kgc.common
package cn.kgc.common{
//锁定锁定作用域
}
package object common{
}
样例类
元祖
特质
18*8=144
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
###############################################
scala jdbc
1、场景:多线程并发,重复消费
重复消费:
排除已经消费(不重复发送)完的,XXX.COMPLETED,renameTo延时,没有延时
排除正在被消费(不重复发送),(标记)
消费部分,又被从头开始消费(重复)
a/b/c/.log 51 ConcurrentHashMap存(线程安全:分段锁)