Scala学习日志——一切从使用开始

摘要

Scala,被称为可伸展的语言。由于其的完全面向对象性却又融合函数式编程,使其代码十分优美,简洁。他可以用寥寥几行就完成在Java中大量代码才能完成的操作。且简单易懂,有效的增强代码的可读性,并减少出错的可能。由于近年来大数据方便Spark一片大好,可以说学大数据必须要学Spark。而总所周知的,Spark的底层是由Scala进行编写的,因此Spark对Scala的适应性是十分好的。因此学习Spark必须先学Scala。不例外的,我也走上了这条道路。

基本中的基本

我不愿意将scala吹得天花乱坠,这里主要是一些小的实践来明确scala究竟是如何用的,更深的东西,等能用了再慢慢研究。

1、定义一些变量

首先,我是从java转向scala的,因此当我使用val时,感觉十分的别扭。不过同理,如果你是从函数式编程语言转入scala的,你同样会觉得var的使用简直就是中亵渎。这里,无论你是从什么语言转向scala,我都建议你多使用val,尽量能够达到整个程序中不出现var。为什么这么说,我一个小例子来进行说明:

//声明函数语法:def 函数名(参数1:参数类型):返回值类型=
def printArgs(args: Array[String]): Unit = {  
    var i = 0  
    while (i < args.length) {
        i += 1  
    }
 } 

这个方法是使用var 并因此属于指令式风格

def printArgs(args: Array[String]): Unit = {
  for (arg <- args)   
      println(arg) 
  }

这是没有使用var的,更函数式。可以简单的看出,不使用var令代码更加的简单易懂,减少了出错的可能。

2. 使用Array与ArrayBuffer

  • 声明定长数组:
    val arr=Array(1,2,3,4) //arr这时为 Array(1,2,3,4)
    如果要声明一个空的数组,可以使用:
    val arr2=new Array[Int]
    Array排序
    println(util.Sorting.quickSort(a))
  • 调用数组的方法:
    arr2(0)="3" //修改arr2(0)的值,注意使用的是()而不是[]

  • 很多时候,我们并不确定数组的长度。亦或许我们要向数组中添加元素,这时就需要可变长的数组,在java中,有ArrayList,scala中则是ArrayBuffer。下面是一些ArrrayBuffer的使用方法,注释写得挺详细的,我便不赘述了。

    //变长数组:ArrayBuffer
    val b=ArrayBuffer[Int]()  //声明
    val c=new ArrayBuffer[Int]()

    /*
    高效操作
     */

    //在ArrayBuffer后添加一个元素
    b += 1;
    for(i <- b) println(i)

    //添加多个元素
    b += (3,5,7,9)
    println(b)

    //添加任意集合
    b ++= Array(2,4,6,8)
    println(b)

    //移除元素
    b.trimEnd(3)
    println(b)
    b.trimStart(3)
    println(b)

    /*
   并不那么高效的操作
    */
    //在下标2前插入6
    b.insert(2,6)
    println(b)
    b.insert(2,7,8,9) //下标2前插入多个数据

    //移除元素
    b.remove(2) //移除下标2
    b.remove(2,3)  //第二个参数表示要移除多少元素
    for(i <- 0 until (b.length,2))  println(b(i))    //两个一跳
    for(i <- (0 until b.length).reverse) println(b(i))  //从后向前循环


    //移除数组中第一个负数之外的所有负数
    val a=Array(1,-1,3,-3,-5,-7,3,4,6,8)
    //首先取到所有不被移除的下标
    var first=true
    val indexs = for(i<- 0 until a.length if first || a(i)>= 0) yield{
      if( a(i)<0 )first=false ; i
    }
    println(indexs)
    //将元素向前移动,再去掉尾部
    for(j <- 0 until indexs.length ) {
      a(j)=a(indexs(j))
      a.toBuffer.trimEnd(a.length-indexs.length)
    }
    for(i <- a  ) print(i+"\t")
    println()

    println(a.sum+" "+a.max+" "+a.min)  //sum输出整个数组的和(必须是数值类型 ),max最大,min最小值,不用非是数值


    //数组排序
    //ArrayBuffer排序
    println(b.sorted)

    val c=ArrayBuffer(1,2,3,4,5,6,7,8,9)
    println(c.sortWith(_>_))  //自己给定算法
  • Array与ArrayBuffer之间可以自由转换。比如上面例子中c.toArray便可将c转化为Array,b.toBuffer便可将b转化为ArrayBuffer。因此当不确定数组长度时,可以先使用ArrayBuffer,操作完成后,再转换回Array便可。

3、声明函数

声明函数没什么可说的,直接上代码了,注释同样挺详细的

//声明函数语法:def 函数名(参数1:参数类型):返回值类型=
def printArgs(args: Array[String]): Unit = {  
    var i = 0  
    while (i < args.length) {
        i += 1  
    }
 } 
//函数参数可以有默认值,不过调用时如果传入参数的话就会替代。
  def decorate(str: String, left: String = "[", right: String = "]") = left + str + right

  //变长参数函数:可以传入不定量的参数,但是不代表着可以传入该参数的数组
  def sum(args : Int*): Int ={
    var result = 0
    for(arg <- args) result += arg
    result
  }
  //递归调用
  def recursiveSum(args : Int*) :Int={
    if(args.length == 0) 0
    else args.head + recursiveSum(args.tail:_*)   
    //tail是所有其他元素的序列,使用:_*来将它转化为参数序列
  }

4、控制语句

类似if,while这些我认为没有太大说的必要。怎么使用其实很简单,这里我只重点说说for循环,因为小生认为scala的for循环十分的强大且优美:

for(i <- 0 to 3) println(i)
    //for循环中可以很复杂,可以有多个参数,实际就像java中的两层循环,一层是i,一层是j。
    //i <- 0 to 3的意思是i遍历0到3
    //scala的for循环中还能加 if 只有能满足 if 的才会被遍历到
    for (i <- 0 to 3; j <- 0 to 3 if (i != 0 && i != j)) print(decorate((i * 10 + j).toString, "<<", ">>") + " ")
    //输出<<10>> <<12>> <<13>> <<20>> <<21>> <<23>> <<30>> <<31>> <<32>>


    //还有一种for循环推到式,当在for循环开头使用yield时,
    // 会生成一个集合,然后将每个循环到的值放入集合
    val a=for (i <- 0 to 3; j <- 0 to 3 if (i != 0 && i != j)) yield decorate((i * 10 + j).toString, "<<", ">>")
    //a=Vector(<<10>>, <<12>>, <<13>>, <<20>>, <<21>>, <<23>>, <<30>>, <<31>>, <<32>>)

5、map,tuple

map映射是一种特殊的tuple,这里我只说说他们的用法。同样在代码里:

  • map的用法:
//构造map
    val scores = Map("wrm" -> 21,"wln" -> 21,"xxw" -> 11)
    //默认构造的是不可变的Map,如需要可变的Map,使用:
    val scores1 =scala.collection.mutable.Map("wrm" -> 21,"wln" -> 21,"xxw" -> 11)

    //如果想先创建一个空的map,需要指定一个Map实现(new) 和给出类型参数
    val nullmap=new HashMap[String,Int]

    println(scores)

    //通过键找到值:
    println(scores("wrm"))
    //判断是否有某个值,有便获得
    val hasValue=if(scores.contains("zzz")) scores("zzz") else 0
    println(hasValue)
    //有种便捷的写法:
    val simplaValue=scores.getOrElse("xxw",0)
    println(simplaValue)


    //map的更新
    //更新某个映射的值:=  如果存在就更新,不存在就新增
    scores1("xxw")=100
    scores1("yxs")=30
    println(scores1)

    //+=用来添加多个关系
    scores1+=("yjl" -> 22,"wzx" ->21)
    println(scores1)
    //-=用来移除某个关系
    scores1-=("yxs")
    println(scores1)

    //上述是对于可变MAP(scala.collection.mutable.Map)
    //对于不可变map,可以这样操作,
    val newmap=scores + ("wrm" -> 23,"wzx" ->21)  //跟新过的map,如果key存在就更新,不存在就新增
    println(newmap)
    //其余操作同理,看似创建了过多的val效率低又浪费资源,其实并非如此——老的映射和新的映射共享大部分资源。(因为他们是不可变的!)


    //map的迭代:
    //十分简单的一个方式
    for((k,v) <- newmap) println("key:"+k+" value:"+v)
    //要反转一个映射——交换k,v位置,可用
    val changeMap=for((k,v) <- newmap) yield (v,k)
    println(changeMap )
  • tunple的用法
    //Tuple的每个参数的数据类型都是不同的如:
    val t=(1,3.14,"Fred")
    //可以使用t._1,t._2或t _1,t _2来进行调用
    println(t _2)   //3.14
    //可以通过模式匹配来使用Tuple
    val (first,second,third)=t
    println(first+"\t"+second+"\t"+third)   //1 3.14    Fred
    //在不需要匹配所有项时,不需匹配的项可以使用_忽略
    val (a,b,_)=t
    println(a+"\t"+b)   //1 3.14

    //拉链操作
    val symbols=Array("<","-",">")
    val counts=Array(2,10,2)
    //可以将两个Array压缩为一个Tuple
    val pairs=symbols.zip(counts)

    //这些对偶可以被一起处理
    for((s,n) <- pairs) Console.print(s * n)  //<<---------->>

今天就进行到这里,接下来会进行更加深入的研究学习。希望这篇博客能帮到有需要的朋友!

码字不易,转发请注明出处!http://blog.csdn.net/qq_28945021/article/details/51970192

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值