Scala

1. Scala和Java的区别:

  • Scala语句后可以没有分号结束;
  • Scala中的Unit相当于Java中的Void;
  • Scala找那个没有String数据类型,使用的是Java中的String;
  • Scala中循环语句没有Break(中断,跳出当前整个循环)和Continue(跳出本次循环,继续下一次循环)关键字。Scala中用if else代替Continue,用面向对象(Breaks.breakable{})来代替Break;
  • Scala中导多个包可以用import****._,"._"相当于Java中的".*";
  • Scala中没有静态语法,Scala是一个完全面向对象的语言,而Java中的静态语法不是面向对象的,在Scala中使用关键字Object来模拟静态语法(编译生成两个文件),可以通过对象名称实现静态操作;
  • Scala中的泛型的返回值类型不能省略;
  • Scala中变量的默认初始化可以使用下划线_(例:var name:String = _),Java中有默认初始化,所以不用赋值,val不能使用_进行初始化;
  • Scala中的访问权限修饰符没有public关键字,只有(default)代表公共的,任何地方都可以使用

2. 定义

Scala是一门多范式的编程语言,其特性有面向对象、函数式编程等。

  • 面向对象:分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题。
  • 函数式编程:将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用这些封装好的功能按照指定的步骤,解决问题。

2.1 面向对象:

Scala是一种纯面向对象的语言,每个值都是对象。对象的数据类型以及行为由类和特质描述。类抽象机制的扩展有两种途径:一种途径是子类继承,另一种途径是灵活的混入机制。这两种途径能避免多重继承的种种问题。、

2.1.1 继承

子类继承父类的属性和方法

2.1.2 封装

属性私有化,对外提供公共的set和get方法对属性进行赋值和获取,

2.1.3 抽象方法

只有声明而没有实现的方法称之为抽象(抽象=>不完整)方法;因为类中包含方法,如果方法为抽象方法,那么类也是抽象类(不能实例化);如果想要构建对象则需要子类继承后补充完整再构建。

def main(args : Array[String]) : Unit = {
    val user = new Child()

    abstract class User {
        //不完整的方法(只有声明,没有实现),称之为抽象方法
        def test() : Unit
    }

    class Child extends User {
        def test() : Unit = {
        }
    }
}
2.1.4 单例对象

定义:在程序运行时,指定类的对象只能创建一个,若单例对象名和类名一致,则称该单例对象为这个类的伴生对象;object关键字声明的是类,也是伴生对象

//伴生类
class User {

//伴生对象
object User {
    def apply() = new User //构造伴生类对象

}

}
2.1.5 特质(trait)

Scala中没有接口的概念,Scala中可以将多个对象中相同的特征从对象中剥离出来,形成一个独立的语法结构,称之为特质;如果一个对象符合这个特征(特质),那么可以将特质混入(作用:增加约束、功能的补充和叠加)这个对象。

1、向类中混入特质,有如下两种方式:

  • 如果存在父类,则采用with;
  • 如果没有父类,则用extends;若需要混入多个特质,则第一个采用extends,后面都采用with;

2、特质的本质是接口(interface),但不要仅仅局限于interface,将特质(trait)理解为interface和abstract class的结合体更好一些。

3、特质的用法:

trait可以在构建对象时,将新的功能混入(添加)到对象中,称之为动态混入。

4、特质初始化顺序:

如果类同时存在父类和特质,则初始化顺序为:父类>特质>当前类。特质的功能执行顺序和初始化顺序相反。

def main(args : Array[String]) : Unit = {
    val user = new User()

trait MyTrait {
    println("2222")
}

class Parent {
    println("1111")
}


class User extends Parent with MyTrait {
    println("3333")
}
}
//结果为:
//1111
//2222
//3333

2.2 函数式编程:

Scala也是一种函数式语言,其函数也能当成值来使用。Scala提供了轻量级的语法用以定义匿名函数,支持高阶函数,允许嵌套多层函数,并支持柯里化。Scala的case class及其内置的模式匹配相当于函数式编程语言中常用的代数类型。更进一步,程序员可以利用Scala的模式匹配,编写类似正则表达式的代码处理XML数据。

  • Scala中的函数表示的是功能的封装,而Java中功能的封装称之为方法;
  • Java中的方法在Scala中就是函数,但是声明在类中的函数叫方法,函数只在当前作用域有效,而方法需要受到类的约束;
  • 函数是功能的封装,也就是说,函数名称不能重复,既没有重写和重载;
  • 函数可以声明在任意位置,而方法只能声明在类中,也可以说方法就是函数,反之不一定;
  • 如果函数名和方法名相同,默认情况下,会调用函数;
  • 方法和对象相关,既可以用this.方法名(),而函数是独立使用的;
  • 在Scala源码中,函数的本质就是方法,函数编译成方法时,增加了修饰符:private static final;
2.2.1 函数的声明和使用:
//TODO 函数的声明和使用
//1.声明:def 函数名 (参数列表) : 返回值类型 = {函数体}
//2.使用:函数名(参数)

//main方法
def main (args: Arrary[String]): Unit = {
    //函数声明
    def test(): Unit = {
        println("test")

    }
    //函数调用
    test()
   //或者是test,函数声明没有参数时,函数的调用可以省略()

}
2.2.2 可变参数:
  • 可变参数因为不确定,所以底层实现时,会采用不同的数组集合实现;
  • 可变参数的位置必须放在参数列表中的最后一项,并且一个参数列表中只能存在一个可变参数;
  • 函数声明参数时,可以进行初始化,声明的参数在调用时是一一对应的;
def main (args: Arrary[String]): Unit = {
    //参数初始化:def fun( password:Int = 00000, name:String* ): Unit = {
    def fun( password:Int, name:String* ): Unit = {
        println("test-----")

    }

    fun(123456, "zhangsan")
}
2.2.3 至简原则:
  • 如果函数体中的逻辑代码需要返回,可以省略return关键字,在Scala语言中,可以将满足条件的最后一行结果作为返回值;
  • 如果函数的逻辑代码只有一行,则可以省略大括号{};
  • 如果能够将返回值推断出返回值类型,则返回值类型可以省略;
  • 如果函数的参数列表中没有声明参数,则小括号()可以省略,既函数调用时也不能加();
  • 等号=可以省略,但是一般和Unit一起省略;
  • 如果函数名称不重要的时候,def和函数名也可以省略,称之为【匿名函数】->(要求:①:def和函数名省略,②:返回值类型省略,有逻辑代码自动推断,③:等号需要增加大于号表示关联);

//1.省略return
def fun1(): String = {
    //return "zhangsan"
    "zhangsan"
}
//println(fun1())


//----------------------------------------
//2省略大括号{}
def fun2(): String = "zhangsan"
//println(fun2())


//----------------------------------------
//3.省略返回值类型
def fun3() = "zhangsan"
//println(fun3())


//----------------------------------------
//4.省略小括号(),省略小括号后在调用时也不能加()
def fun4 = "zhangsan"
//println(fun4)


//----------------------------------------
//4.省略小括号(),省略小括号后在调用时也不能加()
def fun4 = "zhangsan"
//println(fun4)


//----------------------------------------
//5.省略等号,但是一般和Unit同时省略
def fun5() {
 "zhangsan"
}
//println(fun5())


//----------------------------------------
//6.省略def和函数名
() => {
 "zhangsan"
}


2.2.4 函数即为对象:
//函数其实就是对象
def test(): Unit = {

}

//第一种:这里打印的结果为:(),因为打印的是test方法的执行结果
//println(test())

//第二种:test _打印的是对象
//此时,f可以通过编译器自动推断类型,函数对象的类型称之为函数类型
//Function0[Unit]: 0表示函数参数列表中的参数个数,[]中的Unit表示函数没有返回值
val f : Function0[Unit] = test _


//第三种:函数对象作为变量使用
def test(): Unit = {
    println("test scala")

}
//将函数对象复制给一个变量,那这个变量就是函数,既该变量可以传参后执行
val f = test _
f()

//第四种:函数对象作为参数使用
def fun(): Unit = {
    println("test****")
}

def test( f : ()=>Unit ): Unit = {
    f()
}

val f = fun _
test(f)

2.2.5 匿名函数:
def test( f : (Int, Int) => Int): unit = {
    val result = f(10, 20)
    println(result)
}

def sum( x : Int, y : Int): Int = {
    x + y
}
//传统方式
//test(sum)

//TODO:1、如果函数没有名称和def关键字,那么是匿名函数,一般作为参数使用
test(
    ( x : Int, y : Int): Int => {
    x + y
    }
)

//TODO:2、匿名函数作为参数时,可以用【至简原则】
//匿名函数的逻辑代码只有一行,那大括号{}可以省略
test(
    ( x : Int, y : Int): Int => x + y
)

//如果匿名函数的参数类型可以推断出来,那参数类型可以省略
test(
    ( x, y ) => x + y
)

//如果参数列表个数只有一个,那小括号()也可以省略
//如果匿名函数的参数按照顺序只执行一次,那可以用下划线_代替参数,既省略参数列表和箭头
test( _ + _ )



2.2.6 闭包:

如果一个函数使用了外部变量并且改变了此变量的生命周期,将这个变量包含到当前函数的作用域,形成闭合的效果,此效果环境称之为闭包。

闭包的场景:

  • 内部函数使用了外部数据,并改变数据的生命周期
  • 将函数作为对象使用,改变函数本身的生命周期
  • 所有匿名函数都有闭包
  • 内部函数返回到外部使用也存在闭包
def outer( a : Int ) = {
    def inner( b : Int) = {
        a + b
    }
    inner _
}

val inner = outer(10)
val result = inner(20)
println(result) //30
2.2.7 控制抽象:
  • 函数类型只有返回,没有输入称之为抽象,因为不完整;
  • 调用时,不能使用小括号(),在传值时就需要控制;
  • 控制抽象就是将代码作为参数进行传递,(完整的参数传递是将函数对象作为参数进行传递);
//抽象:不完整
def test( f : ()=>Unit ): Unit = {
    f()
} 

//函数只有返回,没有输入,称之为抽象;调用时不能使用()
def test1( f : =>Unit):Unit = {
    f
}

//完整参数传递
test(
    () => {
        println("test----")
    }
)

//控制抽象:将代码作为参数传递
test(
     println("test----")
)

//自定义语法可以使用控制抽象,比如循环中断

2.2.8 函数柯里化:

函数柯里化就是为了将函数简单化,将无关的参数进行分离,可以设定多个参数列表

//原来
def test( a : Int, b : Unit ) = {
    for( i <- 1 to a ) {
        println(i)
    }

    for( i <- 1 to b ) {
        println(i)
    }
}
//a和b没有关系,但是在调用时必须同时传a和b的值,增加耦合性
test(10,20)

//柯里化:将a和b参数分离
def test( a : Int ) ( b : Unit ) = {
    for( i <- 1 to a ) {
        println(i)
    }

    for( i <- 1 to b ) {
        println(i)
    }
}

test(10)  //或者test(10)(20)
2.2.9 递归函数:
  • 基本原则:自己调自己;容易发生栈溢出
  • 递归函数应该有调出递归的逻辑;
  • 递归函数传递参数时需要有规律;
//阶乘
def test( num : Int ) : Int = {
    if( num <= 1 ) {
        1
    } else {
        num * test(num - 1)
    }
}
println(test(5))


//Scala使用了一种特殊的语法优化递归操作:尾(伪)递归
//Scala使用while循环实现伪递归
def test(): Unit = {
    println("test----")
    test() //放在放在代码最后一行
}
test()

3. 集合

集合就是数据的容器,可以容纳数据。

3.1 不可变数组

 Array没有添加和删除的能力(在创建时已经默认初始值为null),只能通过索引的方式修改数据

//1、创建
val array = new Array[String](3) //本质是java:String[] array = new String[3]

//2、修改
//Array访问时的索引采用小括号(),中括号[]代表泛型
ayyay(0) = "zhangsan"
array(1) = "lisi"
array(2) = "wangwu"

//或者第1和2步合并
val array: Array[Int] = Array.apply(1,2,3,4)
//或:val array: Array[Int] = Array(1,2,3,4)

//3、查询
println(array(0))               //第一种方式:索引

println(array.mkString(","))    //第二种方式:将数据变成字符串,用,隔开

//第三种方式:for循环
for (str <- array){
    println(str)
}

//第四种方式:面向对象方式(foreach)
//foreach方法有一个参数,类型是函数类型:String => Unit
def foreachFunction(str : String): Unit = {
    println("******" + str)
}
array.foreach(foreachFunction)

//①将函数作为参数使用时,参数名称重要,而函数名称不是很重要,一般情况下,可以用至简原则
array.foreach(
    (str : String) => {
        println("******" + str)
    }
)

//②
array.foreach(
    (str : String) => println("******" + str)
)

//③
array.foreach(
    (str) => println("******" + str)
)

//④
array.foreach(
    str => println("******" + str)
)

//⑤
array.foreach(println(_))

3.2 可变数组

val array = new ArrayBuffer[Int]()
val array1 = Array(5,6,7,8)

//1、增加
//追加
array.append(1,2,3,4)
array.apendAll(array1)

//插入
array.insert(0, 5)   //第一个位置插入5:(1,2,3,4) => (5,1,2,3,4)

//2、修改
array.update(3, 6)    //(5,1,2,3,4) => (5,1,2,6,4)
array.updated(3, 7)   //会重新创建一个新的数组

//3、删除
array.remove(0)      //删除第一个位置的元素
array.remove(0, 2)   //从第一个位置开始删除两个元素

//4、查询
array.mkString(",")
array.foreach(println)
array.apply(0)  //apply可以省略

//Scala中自定义的集合类型打印后可以直接出现数据
println(array)

可变数组和不可变数组

val array = ArrayBuffer(1,2,3,4)
val array1 = Array(4,5,6,7)

//不可变数组 => 可变数组
val buffer: mutable.Buffer[Int] = array1.toBuffer

//可变数组 => 不可变数组
val array2: Array[Int] = array.toArray

3.3 序列(seq)

定义:有序(数据插入的顺序,而不是大小顺序),可重复的数据集合,且不可变

构建:需要指定泛型,Seq是一个trait,所以无法直接构建对象,一般采用伴生对象的apply方法,底层用的是List集合

Seq也有可变和不可变,其中增删改查和数组差不多

//创建
val seq : Seq[Int] = Seq.apply(1,2,3,4)
//或:
//val list = List.apply(1,2,3,4)
//val list = List(1,2,3,4)

// :: 表示像集合中添加数据,但因冒号结尾,所以计算规则从后往前

3.4 集(Set)

定义:无序,不可重复的数据集合,且不可变

构建:Set是一个trait,不能直接构建对象,也是只用伴生对象apply方法

Set也有可变和不可变

//构建
val set = Set(1,2,3,4)

//可变
val set = mutable.Set(1,2,3,4)

//增加:Set集合没有append、insert方法,因为没有顺序的概念
set.add(5)             //println(set)  => Set(1,2,5,3,4)

//修改:Set集合没有位置的概念,所以无法对指定的位置进行修改,即仅仅是数据的状态修改
set.update(5,false)    //println(set)  => Set(1,2,3,4)
//或:set(5) = true

//删除
set.remove(2)          //println(set)  => Set(1,3,4)

3.5 映射(Map)

定义:存储K-V键值对,无序,K不可重复,V可以重复,默认不可变

构建:Map是一个trait,不能直接构建对象,也是只用伴生对象apply方法

不可变的Map集合的数据基本操作还是特殊符号(如:"::", "+:" 等)

//构建:Scala中kv键值对采用特殊的方法构建
val kv = "a" -> 1
val map = Map(kv, "b" -> 2, "c" -> 3)
//println(map) => Map(a -> 1, b -> 2, c -> 3)

//可变
val map1 = mutable.Map("a" -> 1, "b" -> 2, "c" -> 3)

//增加
map.put("b" , 4)

//修改
map.update("b" , 5)

//删除
map.remove("a")
map.clear()  //清除所有

3.6 元组(Tuple)

定义:Scala采用特殊的方式将无关的数据(元素)作为一个整体,组合在一起,称之为元组。

声明:元组也是一种特殊的集合,采用小括号声明,也有类型。

//TupleN[ClassType....]: "N"是元素个数(最多22个),"ClassType"是元素类型
val t : Tuple3[Int, String, Int] = (1, "zhangsan", 30)
//或:val t : (Int, String, Int) = (1, "zhangsan", 30)

//Tuple元素的访问,无法使用循环操作,因为数据之间没有关系
//如果想要访问其中的数据,可以采用顺序号
println(t._1)
println(t._2)
println(t._3)

3.7 集合之间的转换

//1、List => Array, Set
val list = List(1,2,1,2)

val array : Array[Int] = list.toArray
val set : Set[Int] = list.toSet

//打印
println(list)    //List(1,2,1,2)
println(array)    //[I@511baa65: java中的数组内存地址
println(set)    //Set(1,2): 数据不能重复

//2、同理:Set => List, Array (toList, toArray)

//3、Map => Array, List, Seq, Set
val map = Map(
    ("a", 1), ("b", 2), ("c", 3)
)
val array : Array[(String, Int)] = map.toArray
val list: List[(String, Int)] = map.toList
val set: Set[(String, Int)] = map.toSet

未完待续。。。。。。。。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值