1.def 定义的是一个方法,用下划线可以转换为方法
2.window 换行符是/r/n linux /n
《逐云》
// object 类型代表 一个helloworld的实例
object helloworld {
// 在定义方法的时候,与java类型相反 变量名:数据类型
def main(args: Array[String]): Unit = {
//常量
val num = 100 ;
// 变量两种形式 ,
var str = "hell boy" ;
var str2: String = "ni bu zhidao shiqing "
}
}
if else 的逻辑判断
// Unit 代表方法执行后的返回类型
def method_one(str: String): Unit = {
val num = 3;
// if else 逻辑判断
val num2 = {
if (num > 5) 1 else if (num > 2) 2 else -1;
}
val num3 = if (num > 4) 1 else (); //输出 num3 equal ()
println("num2 equal " + num2);
println("str equal " + str);
println("num3 equal " + num3);
}
> 输出结果 num2 equal 2
> str equal rui
> num3 equal ()
提示
默认返回的是常量值val unit = method_one(“rui”);
println(“method_one ” + unit) //输出结果 method_one (),() 就等于 unit
{…} 内部就被称为块表达式
val num2 = {
if (num > 5) 1 else if (num > 2) 2 else -1;
}
for 循环方式一
// 1 to 100 是一个区间 Range,每次返回的一个值都赋值给 i
for (i <- 1 to 100) {
println(i)
}
for 循环遍历数组
// 数组代表一个区间
val arr = Array ('a', "b" , "av") ;
for (i <- arr) {
println(i)
}
高级for循环
// 每个生成器都可以带一个条件,注意if前面 无 分号
// 双重 for循环
for (i <- 1 to 3 ; j <- 1 to 3 if i != j ) {
// 满足条件进入循环体
print(j + " ")
// 2 3 1 3 1 2
}
Scala中的+ - * / %等操作符的作用与Java一样,位操作符 & | ^ >> <<也一样。只是有
一点特别的:这些操作符实际上是方法。通常来说不需要自定义返回值,系统会正常判断,但是对于递归函数必须要返回值
例子
val str1 = num.+(str)
val i = num.+(num2)
println(str1) // 100hell boy
println(i) // 1100
> 返回值类型可以自动推断出来 不需要重新定义
数组元素的添加,删除,打印
1. 定义数组
定义一个长度为10,类型为String的数组
val arr1 = new Array[String](10);
println(arr1) //[Ljava.lang.String;@58651fd0输出的是hash值
2. 打印数组内容
//2. 将数组转换为数组缓冲就可以看到里面的内容
println(arr1.toBuffer) //ArrayBuffer(null, null, null, null, null, null, null, null, null, null)
3. 向数组中追加内容
//向数组中追加元素
arr3.+=("a"); println(arr3)
4. 向数组中添加数组,但是原来的长度,内容都不会变量
//向数组中追加数组
val arr4 = Array[Int](1,2);
val arr5 = Array[Int](3,4,5);
// ++ 集合不会改变arr4
val arr6= arr4.++(arr5)
5. 数组元素的插入或者移除
val array = Array(1,2,3,4);
val arr1 = ArrayBuffer(1,2,3,4)
// 前面是小标位置,后面的是元素内容
arr1.insert(0,-2,-3)
println(arr1.toBuffer)
arr1.remove(arr1.length)
6. 数组遍历
//初始化一个数组
val arr = Array(1,2,3,4,5,6,7,8)
for(i <- arr) {
println(i)
}
//读取的是小标反转
for(i<- (0 until arr.length).reverse){
print(arr(i))
}
7.数组过滤
val arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
// yield 将原始数组转换为一个新的数组,原始数组不变
val arr1 = for( i <- arr if(i % 2 ==0)) yield i * 10;
println(arr1.toBuffer)
println(arr.toBuffer)
// _ 就代表变量遍历出来的每一个元素
val a = arr1.filter(_ % 2 ==0).map(_* 100);print(a.toBuffer)
println(a.sum)
println(a.max)
println(a.min)
println(a.sorted)
映射关系map
val info = Map("name"->"tom","age"->"23","sex"->"nan")
//有值返回值,没有值返回默认值
println(info("name"));println(info.getOrElse("pp",0))
在映射关系中有个两个map类型,一个长度是否可变来区分
一个是immutable包下的Map,该Map中的内容不可变;另一个是mutable包下的Map,该Map中的内容可变
元组 也是一种映射关系,可以存储各种类型数据
// 定义一个元组
val t = ("123",3.131313,"Pp",1)
// 元组的下标是从一个开始的
println(t._1)
// 将对偶的集合转换为映射
val arr = Array(("p",11),("t",12))
arr.toMap
// 拉杆操作
val rui = Array(10,20,30)
val liu = Array("a","b")
// 对应值进行捆绑
val liuguangrui = rui.zip(liu)
val liuguangrui2 = rui.zipAll(liu,12,"ll")
println(liuguangrui.toBuffer)
println(liuguangrui2.toBuffer)
输出内容
ArrayBuffer((10,a), (20,b))
ArrayBuffer((10,a), (20,b), (30,ll))
Scala的集合有三大类:序列Seq、Set、映射Map,所有的集合都扩展自Iterable特质
在Scala中集合有可变(mutable)和不可变(immutable)两种类型,immutable类型的集合初始化后就不能改变了(注意与val修饰的变量进行区别)
List集合
val left = List(1,2,3)
val right = List(4,5,6)
val uni = left ++ right
println()
println(uni.toArray.toBuffer)
// println(left.++(right).toBuffer) //两个+ 代表加的集合
// println(left.++:(right).toBuffer)
// println(left.+:("sdfdsf").toBuffer) //:就相当于头部
// println(left.:+("sdfdsf").toBuffer.head) //第一个元素
// println(left.:+("sdfdsf").toBuffer.tail) //除一个元素外的其他元素
Set集合
// 两个集合交集
val ints = set & set1
//在第一个集合基础上 去掉第二个集合重复元素
val ints1 = set -- set1
//并集
val ints2 = set ++ set1
// 返回第一个不同于第二个集合元素
val ints3 = set1 &~ set //set1.diff(set)
// 大于6的元素
val i = set.count(_>=6)
// 从角标0 开始 取代 2个元素
val ints4 = set.slice(0,2)
val unit = set1.subsets(2).foreach(x=>println(x))
定义一个可变长度
set1 += 1 ; println(set1.toBuffer)
set1.add(2); println(set1.toBuffer)
set1 ++=Set(1,4,5);println(set1)
Map集合
// 长度不可以改变,不可以去添加或者删除
val map1 = Map("rui" -> 12,"wen"->21) ; println(map1.toBuffer)
val keys = map1.keys;println(keys.toBuffer)
val set = map1.keySet;println(set.toBuffer)
// 长度可以变化
val user =mutable.HashMap("zhangsan"->50,"lisi" -> 100)
user +=("wangwu" -> 30);println(user.toBuffer)
user("zhangsan") = 55;println(user.toBuffer) //修改键
user -=("zhangsan") //删除键
user += ("zhangsan" -> 60, "lisi" -> 50) //添加键
user.remove("zhangsan0") // 删除键
// 遍历map方法
for((x,y) <- user) println(x+" -> "+y) // for循环
for(x<- user.keys) println(x+" -> "+user(x)) //键集 获取值
user.foreach{case (x,y) => println(x+" -> "+y)} //foreach 循环遍历
类
类型一
// 主构造器 会执行类中定义所有语句,方法解析不执行
class Person (val nameStr:String,val age : Int){
// val 修饰的变量,只有get方法 无set方法
val id = "9527".toInt
val str: String = "rui"
//类私有字段,只能在类的内部使用
private var name: String = "唐伯虎"
//对象私有字段,Person类的方法只能访问到当前对象的字段
private[this] val pet = "小强"
var gender = "nan" ; //get,set都有
//辅助构造器,第一行必须要调用主构造器
// def this(name : String,age :Int,gender:String){
// this(name,id);
// this.gender = gender
// }
}
类型二
class Queen (val name : String ,prop : Array[String],private var age : Int=23) {
println(prop.length)
// 由于age被private修饰,隐藏 age , name 都等同于被private修饰
def description = name + " is " + age + " years old with " + prop.toBuffer
}
object Queen{
def main(args: Array[String]) {
//私有的构造器,只有在其伴生对象中使用
val q = new Queen("itcast", Array("黑马", "博学谷"), 10)
println(q.description)
}
}
对象 由于在scala中没有静态方法字段,因此通过object达到同静态方法字段同样的效率
伴生对象 1. 在一个文件中, 类名与object名字相同,彼此可以相互访问
// 通过object达到同静态方法字段同样的效率
class SingleDemo {
def main(args: Array[String]): Unit = {
val demo: SingleDemo = SessionFactory.getSession()
println(demo)
}
}
object SessionFactory{
//该部分相当于java中的静态块
var counts = 5
val sessions = new ArrayBuffer[SingleDemo]()
while(counts > 0){
sessions += new SingleDemo
counts -= 1
}
//在object中的方法相当于java中的静态方法
def getSession(): SingleDemo ={
sessions.remove(0)
}
}
Scala中isInstanceOf 和 asInstanceOf 区别
is是先判断 q.isInstanceOf(a)q是a的一个实例,只能判断q是a子类或者其实体类
q.asInstanceOf(a)将q转为a,通常来说都是先判断后转
如果对象是 null,则 isInstanceOf 一定返回 false, asInstanceOf 一定返回 null;
//判断p是否为Person4类的实例
println(p.isInstanceOf[Person4])//true
//判断p的类型是否为Person4类
println(p.getClass == classOf[Person4])//false
//判断p的类型是否为Student4类
println(p.getClass == classOf[Student4])//true
可以向下面这样写
val p:Person5=new Student5
p match {
// 匹配是否为Person类或其子类
case per:Person5 => println("This is a Person5's Object!")
// 匹配所有剩余情况
case _ =>println("Unknown type!")
}
匿名内部类
//匿名内部类
class Person8(val name:String) {
def sayHello="Hello ,I'm "+name
}
class GreetDemo{
def hell(person8 : Person8{
def sayHello : String
}) ={
println(person8.sayHello)
}
}
object GreetDemo {
def main(args: Array[String]) {
//创建Person8的匿名子类对象
val p=new Person8("tom")
val g=new GreetDemo
g.hell(p)
}
}
重写抽象类
// 抽象方法
abstract class Person9 (val name:String){
//必须指出返回类型,不然默认返回为Unit
def sayHello:String
def sayBye:String
}
// 在子类中覆盖抽象类的抽象方法时,可以不加override关键字;
class Student9(name:String) extends Person9(name){
//必须指出返回类型,不然默认
def sayHello: String = "Hello,"+name
def sayBye: String ="Bye,"+name
}
object Student9{
def main(args: Array[String]) {
val s = new Student9("tom")
println(s.sayHello)
println(s.sayBye)
}
}
//抽象类中 字段没有给出初始值的话,子类集成抽象类后需要复写
abstract class Person10 (val name:String){
//抽象fields
val age:Int
}
class Student10(name: String) extends Person10(name) {
val age: Int = 50
}
trait LoggedTrait {
// 该方法为实现的具体方法
def log(msg: String) = {println("sdfdsf")}
}
trait MyLogger extends LoggedTrait{
// 覆盖 log() 方法
override def log(msg: String) = println("log: " + msg)
}
class PersonForMixTraitMethod(val name: String) extends LoggedTrait {
def sayHello = {
println("Hi, I'm " + this.name)
log("sayHello method is invoked!")
}
}
object PersonForMixTraitMethod{
def main(args: Array[String]) {
val tom= new PersonForMixTraitMethod("Tom").sayHello //结果为:Hi, I'm Tom sdfdsf
// 使用 with 关键字,指定混入MyLogger trait
val rose = new PersonForMixTraitMethod("Rose") with MyLogger
rose.sayHello
// 结果为: Hi, I'm Rose
// 结果为: log: sayHello method is invoked!
}
}
//3. 最后走本类的苟泽
//1
class Person_One {
println(“Person’s constructor!”)
}
//2
trait Logger_One {
println(“Logger’s constructor!”)
}
//3
trait MyLogger_One extends Logger_One {
println(“MyLogger’s constructor!”)
}
//4
trait TimeLogger_One extends Logger_One {
println(“TimeLogger’s contructor!”)
}
// 1. 类与类之间 先走父类
//2. trait之间先走父类,从左到右的顺序
//3. 最后走本类的苟泽
//5
class Student_One extends Person_One with MyLogger_One with TimeLogger_One {
println(“Student’s constructor!”)
}
object exe_one {
def main(args: Array[String]): Unit = {
val student = new Student_One
//执行结果为:
// Person’s constructor!
// Logger’s constructor!
// MyLogger’s constructor!
// TimeLogger’s contructor!
// Student’s constructor!
}
}
case匹配模式数据类型与内容匹配
val arr = Array("hadoop", "zookeeper", "spark")
val name = arr(Random.nextInt(arr.length))
// 内容匹配
name match {
case "hadoop" => println("大数据分布式存储和计算框架...")
case "zookeeper" => println("大数据分布式协调服务框架...")
case "spark" => println("大数据分布式内存计算框架...")
case _ => println("我不认识你...")
}
val arr1 = Array("hello", 1, 2.0, CaseDemo01)
val v = arr1(Random.nextInt(4))
// 类型匹配
v match {
case x: Int => println("Int " + x)
case y: Double if(y >= 0) => println("Double "+ y)// 匹配的时候还可以添加守卫条件
case z: String => println("String " + z)
case _ => throw new Exception("not match exception")
}
// 集合匹配
val lst = List(3, -1)
lst match {
case 0 :: Nil => println("only 0")
case x :: y :: Nil => println(s"x: $x y: $y")
case 0 :: tail => println("0 ...")
case _ => println("something else")
}
// 元组匹配
val tup = (2, 3, 7)
tup match {
case (1, x, y) => println(s"1, $x , $y") //输出格式,前面必须是s
case (_, z, 5) => println(z)
case _ => println("else")
}
//引用类型匹配
val arr = Array(CheckTimeOutTask, HeartBeat(12333), SubmitTask("0001", "task-0001"))
arr(Random.nextInt(arr.length)) match {
case SubmitTask(id, name) => {
println(s"$id, $name")
}
case HeartBeat(time) => {
println(time)
}
case CheckTimeOutTask => {
println("check")
}
}
//map类型匹配
val map = Map("a" -> 1, "b" -> 2)
val v = map.get("b") match {
case Some(i) => i
case None => 0
}
//PartialFunction[A, B] A代表参数类型 B代表返回值
def func1: PartialFunction[String, Int] = {
case "one" => 1
case "two" => 2
case _ => -1
}
协变、逆变、非变总结
C[+T]:如果A是B的子类,那么C[A]是C[B]的子类。
C[-T]:如果A是B的子类,那么C[B]是C[A]的子类。
C[T]: 无论A和B是什么关系,C[A]和C[B]没有从属关系。
Scala的上下边界特性允许泛型类型是某个类的子类,或者是某个类的父类;
(1) U >: T
这是类型下界的定义,也就是U必须是类型T的父类(或本身,自己也可以认为是自己的父类)。
(2) S <: T
这是类型上界的定义,也就是S必须是类型T的子类(或本身,自己也可以认为是自己的子类)。