zoukankan      html  css  js  c++  java
  • scala

    推荐书籍,快学scala

    val str="i love scala"  //编译器自动确定类型,使用val定义的变量值是不可变的,相当于java里用final修饰的变量

    val i = 1

    var s="hello"    //使用var定义的变量是可变的,再scala中鼓励使用val

    val stri: String ="alex"   //scala编译器会自动推断变量的类型,必要的时候可以指定类型,变量名在前,类型在后

    常用的变量类型: Byte,Char,Short,Int,Long,Float,Double,Boolean

    if例子:val y = if(x >0) 1 else -1

    if例子:val z=if(x>0) 1 else "error"  //在未赋值时,可以是数值,也可以是字符串。但是他的类型变成了"Any"

    if例子:val m =if(x >2) 1   //如果x不大于2,那么是未赋值。返回值是m: AnyVal=()。在scala中每个表达式都有值,scala仲有个Unit类,写做(),相当于java中的void

    object 单例对象

    class 类

    trait 相当于java中的接口

    块表达式:

    object BlockExpressionDemo {
    def main(args: Array[String]): Unit = {
    val x=0
    val result={ //这是一个块表达式,块中最后一个表达式的值就是块的值
    if(x<0){
    -1
    }else if(x>=1){
    1
    }else {
    "error"
    }
    }
      println(result);
    }
    }

    数组例子:

    val arr=Array(1,2,3)

    val arr2=(1 to 10)

    val arr3=Array(1 to 10)   //这样是错的,

    arr(1)=100

    for循环:

    1 to 10  //会返回一个scala的Range(1,2,3,4,5,6,7,8,9,10)

    for(i <- 1 to 10){
    println(i)
    }
    val a1=(1 to 9)
    for(i <- 0 until a1.length) println(i) //打印出来的0-8

    高级for循环: //注意:if前面没有分号

    for(i<- 1 to 3; j <- 1 to 3 if i!=j){
    print((10 * i + j )+" ")
    }

    for推导式

    val v = for (i <- 1 to 10) yield i*10    //yield生成一个新的集合数组
    println(v)//会发现v是一个新集合 Vector(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)

    map例子:

    val z=(1 to 10).map(_*10)  //也可以写成 (1.to(10).map(_*10),也是返回一个Vector数组
    println(z)
    val f1=(x:Int) => x * 10
    val r= 1 to 10
    r.map(f1)

    filter例子:

    val a1=(1.to(9))
    val a2=a1.filter(_%2==0) //filter也是返回一个新数组

    until方法:

    val a1=(1 to 9)
    0 util a1.legnth
    for(i <- 0 until a1.length) println(i) //打印出来的0-8

    定义方法和函数,函数和方法是有区别的,函数可以作为一个值传到方法里

    方法:

    def m1(x: Int, y: Int) : Int = x * y      //x: Int 参数列表    : Int 方法返回值类型  方法的返回值类型可以不写,编译器可以自动推断,但是对于递归函数,必须指定返回类型

    调用val r=m1(3,5)

    定义没有返回值的方法:

    def m2(name:String): Unit ={
      println(name)
    }
    val v=m2("alex")
    print(v)

    匿名函数:

    val abc=(x:Int,y:Int) => x+y   

    val func=(x:Int,y:Double) => (y,x) //返回值是一个元组

    val func2:(Int,Double) => (Double,Int) = {(a,b) => (b,a) }   //(a,b)代表前面(Int,Double)的局部变量   和上面例子的效果一样

    简单版匿名函数传入方法的例子:

    val f1=(x:Int) => x * 10
    val f2=(x:Int) => x+10
    val r= 1 to 10
    r.map(f1)
    r.map(f2)
    r.map((x:Int) => x*100) //直接定义一个匿名函数
    r.map(x => x*100) //同上面一样效果,更简洁
    r.map(_*100) //同上面一样效果,最简洁
    val arr=1 to 9
    val r1=arr.map(x=>x*5) //产生一个新数组r1
    val r2=arr.map(x=>x-1) //产生一个新数组r2
    println(r1) //打印数组
    println(r1.toBuffer) //把r1变成一个ArrayBuffer

    完整版匿名函数传入方法的例子:

    object HelloScala{
    def main(args: Array[String]): Unit = {
    println(m1(func))
    }
    val func = (x:Int) => x*10
    def m1(f:Int => Int) : Int={ //表示需要传入一个Int参数,返回一个Int值,
    //在方法体里调用函数
    f(3)
    }
    }

    高级版定义匿名函数的例子:

     val func:Int  =>  String  = { x => x.toString }  //传入一个Int     =>是返回值,返回一个String   后面必须有大括号函数体    要有一个变量x接收传进来Int,这个x是一个局部变量

    调用func(10)    就返回一个String

    将方法转换成函数(神奇的下划线)

    def m2(x:Int,y:Int) :Int =x+y  //定义一个方法

    scala> def m2(x:Int,y:Int) :Int =x+y 

    m2: (x: Int, y: Int)Int

    val f2=(a:Int,b:Int) => a+b   //定义一个函数

    val f3=m2 _    //把方法m2变成了函数

    数组,映射,元组,集合

    数组:定长数组和变长数组

    val arr=new Array[Int](10)    //装Int的数组,长度为10,里面值是0

    println(arr)   //直接打印定长数组,内容为数组的hashcode值

    println(arr.toBuffer)  //将数组转换成数组缓冲,就可以看到原数组中的内容了,toBuffer会将数组转换成数组缓冲

    arr(0)=1   //赋值

    arr(1)=2

    val arr1=Array(1,3,4,5,6)   //定义一个长度为5的数组

    val arr2=Array[Int](10)   //这里没new,这样只创建了一个长度为1的数组,里面只有一个值为10

    println(arr2.toBuffer)  //ArrayBuffer(10),长度为1的数组,里面只有一个值为10

    变长数组(数组缓冲):

    ArrayBuffer,如果想使用数组缓冲,需要导入import scala.collection.mutable.ArrayBuffer包

    val ab=ArrayBuffer[Int]()

    ab+=1

    ab+=(2,3,4,5) //追加多个元素

    ab++=Array(6,7)  //追加一个数组用两个加号 ++=

    ab++=ArrayBuffer(8,9)   //追加一个数组缓冲

    ab.insert(0,-1,0)   //在数组某个位置插入元素用insert  ,这里在数组的0下标上插入了两个数字-1和0

    ab.remove(8,2)  //删除数组某个位置的元素用remove,这里删除了下表8开始的2个元素

    遍历数组:

    1.增强for循环 

    val arr=Array(1,2,3,4,5,6)

    for(i <- arr)

      println(i)

    2.好用的uttil会生成脚标,0 until 10  包含0不包含10

    for(i <- (0 until arr.length).reverse)   //reverse反转

      println(arr(i))

    val a1=ArrayBuffer(8,2,3)

    a1.map(print)

    a1.map(println)

    a1.map(println(_))

    数组的转换:

    yield关键字将原始的数组进行转换会产生一个新的数组

    val a =Array(1,2,3,4,5)

    for(i<- a) yield i * 10

    a.map(x=>x*10) //效果和上面相同

    a.map((x:Int)=>x * 10)  //效果和上面相同

    a.map( _ * 10)   //效果和上面相同

    数组转换小例子:

    val arr=Array(1,2,3,4,5,6,7,8,9)

    //将偶数取出,再乘以10,生成一个新的数组

    val res=for (e <- arr if e%2==0) yield e*10   //第一种方法

    arr.filter((x:Int) => x%2 ==0 )     //传进来一个Int,返回一个布尔值  , 最后结果是2,4,6,8

    arr.filter(x=> x %2 ==0)        //上面的简单版,最后结果是2,4,6,8

    arr.filter( _ % 2 ==0)    //更简洁版,最后是2,4,6,8

    arr.filter( _ % 2 ==0).map( _ * 10)    //正确答案

    其他例子:arr.sum    //返回值45

    val arr=Array(2,5,1,4,7,3)

    arr.sorted   //返回值1,2,3,4,5,6,7

    arr.sorted.reverse   //返回值7,6,5,4,3,2,1

    arr.sortBy(x => x)   //返回值1,2,3,4,5,6,7

    arr.sortWith( _>_ )   //返回值7,6,5,4,3,2,1 ,从大到小

    arr.sortWith( _<_ )   //返回值1,2,3,4,5,6,7,从小到大

    arr.sortWith((x,y) => x< y )   //返回值1,2,3,4,5,6,7

    映射:

    构建映射:

    val m=Map("a" -> 1, "b" -> 2)   //创建的时候是immutable.Map  不可改变

    m("a")  //访问

    m("a") =2   //报错,不可改变,

    import scala.collection.mutable.Map

    val mm=Map("i"->1, "j" ->2)  //创建的是mutable的map,可以改变

    mm("i")=10    //可以

    mm("k")=20 //可以

    mm+=("o" -> 6) //可以

    mm+=(("o",6))  //可以

    import java.util.HashMap   //可以引入java的包

    val hm=  new HashMap()

    val m = Map(("a",1) ,("b" ,2))    //其实映射里装的是元组,都是对偶元组

    访问映射:

    m.getOrElse("c",0)    //如果m里面没有c,不会报错 ,给他个0

    元组:

    val t=(1,"spark",2.0)  //返回一个(Int, String, Double)

    访问:

    val r=t._2   //取出spark

    val pair=("t",5)  //定义一个对偶元组

    val m = Map(("a",1) ,("b" ,2)) 

    把上面的pari装入m

    m+= pair   //res5: m.type = Map(t -> 5, b -> 2, a -> 1)

    m+=(("y",6),("z",3))  // res6: m.type = Map(z -> 3, t -> 5, b -> 2, y -> 6, a -> 1)

    特殊的例子:

    val t=("a",  1,  2.0) 

    t._2

    res0: Int = 1

    scala> t._1

    res1: String = a

    val t,(x,y,z)=("a",1, 2.0)

    t: (String, Int, Double) = (a,1,2.0)

    x: String = a

    y: Int = 1

    z: Double = 2.0

    scala> x

    res2: String = a

     将对偶的集合转换成映射:

    scala> val arr=Array(("a",1),("b",2))

    arr: Array[(String, Int)] = Array((a,1), (b,2))

    scala> arr.toMap    //转换成了map

    res3: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)

    拉链操作:

    scala> val a=Array("a","b","c")

    a: Array[String] = Array(a, b, c)

    scala> val b=Array(1,2,3)

    b: Array[Int] = Array(1, 2, 3)

    scala> a.zip(b)

    res4: Array[(String, Int)] = Array((a,1), (b,2), (c,3))

    如果拉链多出来一截:

    scala> val b=Array(1,2,3,4)

    b: Array[Int] = Array(1, 2, 3, 4)

    scala> a.zip(b)

    res5: Array[(String, Int)] = Array((a,1), (b,2), (c,3))   //多出来的一截自动没有

    集合:

    集合有三大类:序列Seq,集Set,映射Map,所有集合都扩展子Iterable特质。集合有可变和不可变的两种类型。

    val lst=List(1,3,4,5,6)

    val list=List(1,2,3)

    list(0)   //取值

    list(0)=10  //报错,不可变

    导包:

    import scala.collection.mutable.ListBuffer

    val lb=ListBuffer(1,2,3)

    lb(1)=200 //可以改变值了

    scala> lb

    res7: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 200, 3)

    scala> lb.map(_ * 10)   //新生成一个List

    res8: scala.collection.mutable.ListBuffer[Int] = ListBuffer(10, 2000, 30)

    val lst1=List(1,2,3)

    val lst2=0::lst1  //将0插入到lst1的前面生成一个新的List

    val lst3=lst1.::(0)  //效果同上

    val lst4=0+:lst1  //效果同上

    val lst5=lst1.+:(0)  //效果同上

    val lst6=lst1 :+3   //将一个元素添加到lst1的后面产生一个新的集合

    val lst0=ListBuffer[Int](1,2,3)

    val lst1 = new ListBuffer[Int]

    lst1 +=4   //追加4

    lst1.append(5)   //追加5

    lst1 +=(8,9)  //追加多个元素

    lst2 = ListBuffer(10)   //创建一个新集合

    lst1 ++=lst2  //把lst2加到lst1里  和 ArrayBuffer里面一样

    val lst3=lst1++lst2  //两集合相加,并生成一个新集合

    List小例子:

    val lst=List(1,3,2,7,5,9,6,4,8)   //创建一个List

    val lst1=lst.sorted   //从大到小排序

    val it = lst1.grouped(5)   //创建了一个iterator

    val lst2=it.toList   //查看it里的两个集合,将iterator转换成List, lst2里有两个List,大List套了两个小List

    lst2(0)   //访问第一个list

    val lst3=lst2.flatten    //把lst2中的两个小list,平铺成一个大List

    例子:单机版WordCount

    val lines =List("hello tom hello jerry","hello tom kitty hello hello")

    lines.map(_.split(" "))   //用空格来切 ,结果是res35: List[Array[String]] = List(Array(hello, tom, hello, jerry), Array(hello, tom, kitty, hello, hello))

    lines.map(_.split(" ")).flatten    //上面切完以后,用flatten,编程一个大集合  res36: List[String] = List(hello, tom, hello, jerry, hello, tom, kitty, hello, hello)

    //比上面更好的方法

    val words=lines.flatMap(_.split(" "))      //flatMap想当与先做了map再做flat操作。

    val wordsAndOne = words.map((_,1))    //返回一个List,list里装的是对偶元组。wordsAndOne: List[(String, Int)] = List((hello,1), (tom,1), (hello,1), (jerry,1), (hello,1), (tom,1), (kitty,1), (hello,1), (hello,1))

    val grouped = wordsAndOne.groupBy(_._1)   //第一个_ 代表每个元组例如(hello,1),   第二个_1代表每个元组里的第一个元素,例如hello。   grouped: scala.collection.immutable.Map[String,List[(String, Int)]] = Map(tom -> List((tom,1), (tom,1)), kitty -> List((kitty,1)), jerry -> List((jerry,1)), hello -> List((hello,1), (hello,1), (hello,1), (hello,1), (hello,1)))

    //不用执行,可以看看 val result =grouped.map(_._1)               //返回一个List。请比较一下val result =grouped.map(_._2) 的区别。 还有,请试试val result=grouped.keys 这个返回是一个Set(tom,kitty,jerry,hello)

    result: scala.collection.immutable.Iterable[String] = List(tom, kitty, jerry, hello)

    val result = grouped.map(t => (t._1,t._2.size))      //t是对偶元组tom->List((tom,1),(tom,1))     t._1是key,就是tom,  t._2是List,然后取他的size。 最后结果result: scala.collection.immutable.Map[String,Int] = Map(tom -> 2, kitty -> 1, jerry -> 1, hello -> 5)

    val finalResult = result.toList.sortBy(_._2)   //  _是元组,按照次数排序。升序finalResult: List[(String, Int)] = List((kitty,1), (jerry,1), (tom,2), (hello,5))

    val finalResult = result.toList.sortBy(_._2).reverse  //降序

    val finalResult = result.toList.sortBy(_._2).reverse.filter(_._2>1)   //过滤1次以上的数据

    finalResult: List[(String, Int)] = List((hello,5), (tom,2))

    //上面的简化版

    val lines =List("hello tom hello jerry","hello tom kitty hello hello")

    val grouped = lines.flatMap(_.split(" ")).map((_,1)).groupBy(_._1) 

    val result=grouped.mapValues(_.size)     //  _代表每个List,例如List((tom,1),(tom,1))    mapValues不动key,所以还是tom,kitty,jerry等,统计的是values,也就是每个List

    fold例子:

    val a=Array(1,2,3,4,5,6)

    a.sum   //21

    a.reduce (_+_)    //reduce把里面内容进行汇总 ,结果21     (((1+2)+3)+4)  从左开始加    默认调用reduceLeft

    a.reduce(_-_)   //-19

    a.par   //返回一个可以并行化操作的集合res0: scala.collection.parallel.mutable.ParArray[Int] = ParArray(1, 2, 3, 4, 5, 6)

    a.par.reduce(_+_)   //21  

    fold(10)(_+_)   //蜕化。可以传2个参数。

    a.fold(10)(_+_)    //31  给了个初始值10,

    fold也支持并行化计算

    a.par.fold(10)(_+_)   //61

    Set:

    不可变的Set: import scala.collection.immutable.HashSet

    val set1 = new HashSet[Int]()

      //将元素和set1合并生成一个新的set,原有set不变

    val set2 = set1 + 4

          //set中元素不能重复

    val set3 = set1 ++ Set(5, 6, 7)

    val set0 = Set(1,3,4) ++ set1

    println(set0.getClass)

                

     可变的Set: 

    import scala.collection.mutable

     

    object MutSetDemo extends App{

          //创建一个可变的HashSet

            val set1 = new mutable.HashSet[Int]()

              //向HashSet中添加元素

                set1 += 2

                  //add等价于+=

                    set1.add(4)

                      set1 ++= Set(1,3,5)

                        println(set1)

                          //删除一个元素

                            set1 -= 5    

                              set1.remove(2)

                                println(set1)

    }

    Map:也分为可变和不可变

    object MutMapDemo extends App{

          val map1 = new mutable.HashMap[String, Int]()

            //向map中添加数据

              map1("spark") = 1

                map1 += (("hadoop", 2))

                  map1.put("storm", 3)

                    println(map1)

     

                      //从map中移除元素

                        map1 -= "spark"

                          map1.remove("hadoop")

                            println(map1)

    }

    object伴生对象,里面一般存放静态对象,类似于java中的静态变量,静态方法。

    scala的hello world

    object HelloScala {   //object 伴生对象,单例对象

      def main(args: Array[String]) {   //所有定义在object里的方法,都是静态方法,相当于java中所有方法加上了static

        println("hello scala,I love u")    

      }

    }

    scala里的类

    //在Scala中,类并不用声明为public。

    //Scala源文件中可以包含多个类,所有这些类都具有公有可见性。

    class Person {

          //用val修饰的变量是只读属性,有getter但没有setter

            //(相当与Java中用final修饰的变量)

              val id = "9527"

     

                //用var修饰的变量既有getter又有setter

                  var age: Int = 18

     

                    //类私有字段,只能在类的内部使用

                      private var name: String = "唐伯虎"

     

                        //对象私有字段,访问权限更加严格的,Person类的方法只能访问到当前对象的>字段

                          private[this] val pet = "小强"

    }

    构造器:

    注意:主构造器会执行类定义中的所有语句

    /**
    *每个类都有主构造器,主构造器的参数直接放置类名后面,与类交织在一起
    */
    class Student(val name: String, val age: Int){
    //主构造器会执行类定义中的所有语句
    println("执行主构造器")

    try {
    println("读取文件")
    throw new IOException("io exception")
    } catch {
    case e: NullPointerException => println("打印异常Exception : " + e)
    case e: IOException => println("打印异常Exception : " + e)
    } finally {
    println("执行finally部分")
    }

    private var gender = "male"

    //用this关键字定义辅助构造器
    def this(name: String, age: Int, gender: String){
    //每个辅助构造器必须以主构造器或其他的辅助构造器的调用开始
    this(name, age)
    println("执行辅助构造器")
    this.gender = gender
    }
    }
    /**
    *构造器参数可以不带val或var,如果不带val或var的参数至少被一个方法所使用,
    *那么它将会被提升为字段
    */
    //在类名后面加private就变成了私有的
    class Queen private(val name: String, prop: Array[String], private var age: Int = 18){

    println(prop.size)

    //prop被下面的方法使用后,prop就变成了不可变得对象私有字段,等同于private[this] val prop
    //如果没有被方法使用该参数将不被保存为字段,仅仅是一个可以被主构造器中的代码访问的普通参数
    def description = name + " is " + age + " years old with " + prop.toBuffer
    }

    object Queen{
    def main(args: Array[String]) {
    //私有的构造器,只有在其伴生对象中使用
    val q = new Queen("hatano", Array("蜡烛", "皮鞭"), 20)
    println(q.description())
    }
    }
    6.2.1.  单例对象
    在Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的
    1.存放工具方法和常量
    2.高效共享单个不可变的实例
    3.单例模式

    ackage cn.itcast.scala

    import scala.collection.mutable.ArrayBuffer

    /**
    * Created by ZX on 2015/11/14.
    */
    object SingletonDemo {
    def main(args: Array[String]) {
    //单例对象,不需要new,用【类名.方法】调用对象中的方法
    val session = SessionFactory.getSession()
    println(session)
    }
    }

    object SessionFactory{
    //该部分相当于java中的静态块
    var counts = 5
    val sessions = new ArrayBuffer[Session]()
    while(counts > 0){
    sessions += new Session
    counts -= 1
    }

    //在object中的方法相当于java中的静态方法
    def getSession(): Session ={
    sessions.remove(0)
    }
    }

    class Session{

    }

    6.2.2. 伴生对象
    在Scala的类中,与类名相同的对象叫做伴生对象,类和伴生对象之间可以相互访问私有的方法和属性
    package cn.itcast.scala

    /**
    * Created by ZX on 2015/11/14.
    */
    class Dog {
    val id = 1
    private var name = "itcast"

    def printName(): Unit ={
    //在Dog类中可以访问伴生对象Dog的私有属性
    println(Dog.CONSTANT + name )
    }
    }

    /**
    * 伴生对象
    */
    object Dog {

    //伴生对象中的私有属性
    private val CONSTANT = "汪汪汪 : "

    def main(args: Array[String]) {
    val p = new Dog
    //访问私有的字段name
    p.name = "123"
    p.printName()
    }
    }

    6.2.3. apply方法
    通常我们会在类的伴生对象中定义apply方法,当遇到类名(参数1,...参数n)时apply方法会被调用
    package cn.itcast.scala

    /**
    * Created by ZX on 2015/11/14.
    */
    object ApplyDemo {
    def main(args: Array[String]) {
    //调用了Array伴生对象的apply方法
    //def apply(x: Int, xs: Int*): Array[Int]
    //arr1中只有一个元素5
    val arr1 = Array(5)
    println(arr1.toBuffer)

    //new了一个长度为5的array,数组里面包含5个null
    var arr2 = new Array(5)
    }
    }


    6.2.4. 应用程序对象
    Scala程序都必须从一个对象的main方法开始,可以通过扩展App特质,不写main方法。

    package cn.itcast.scala

    /**
    * Created by ZX on 2015/11/14.
    */
    object AppObjectDemo extends App{
    //不用写main方法
    println("I love you Scala")
    }
  • 相关阅读:
    页面的三大家族
    封装函数
    图片自动播放的案例
    动画封装
    长图滚动案例+点名册案例
    时钟案例
    伪随机数,随机数种子seed
    numpy.tolist( )函数
    countif( ) 函数判断当前单元格的身份证号码是否重复出现
    Excel技巧
  • 原文地址:https://www.cnblogs.com/alexhjl/p/8108583.html
Copyright © 2011-2022 走看看