scala Learning

  • Scala 与 Java 的最大区别是:Scala 语句末尾的分号 ; 是可选的。
  • 大小写敏感
  • 类名第一个字母大写
  • 方法名第一个字母小写
  • 定义包 package
  • 引入包 import java.awt._ // 引入包内所有成员

基本数据类型和操作

基本数据类型

Scala的数据类型包括:Byte、Char、Short、Int、Long、Float、Double和 Boolean。对于字符串,Scala用java.lang.String 类来表示字符串。

操作符

  • 在Scala中,可以使用加(+)、减(-) 、乘(*) 、除(/) 、余数(%)等操作 符,而且,这些操作符就是方法。例如,5 + 3和(5).+(3)是等价的。

  • 在Scala中并没有提供++和–操作符。

富包装类

  • 对于基本数据类型,除了以上提到的各种操作符外,Scala 还提供了许多常用运算的方法,只是这些方法不是在基本类 里面定义,还是被封装到一个对应的富包装类中

  • 每个基本类型都有一个对应的富包装类,例如Int有一个 RichInt类、String有一个RichString类,这些类位于包 scala.runtime中

  • 当对一个基本数据类型的对象调用其富包装类提供的方法, Scala会自动通过隐式转换将该对象转换为对应的富包装类 型,然后再调用相应的方法。例如:3 max 5

Range

可以用一下命令来产生for循环时的数值序列:

1 to 5 
1 util5
1 to 10 by 2

输入

import scala.io._. // read_xxx 在这个包中
var i = readInt()
var l = readLine()
var c = readChar()
var b = readBoolean()

输出

print()println()printf()

读写文件

  • Scala 进行文件写操作,直接用的都是 java中 的 I/O 类 (java.io.File)
import java.io._

object Test {
   def main(args: Array[String]) {
      val writer = new PrintWriter(new File("test.txt" ))

      writer.write("菜鸟教程")
      writer.close()
   }
}

  • 可以使用Scala.io.Source的getLines方法实现对文件中所 有行的读取
import scala.io.Source

object Test {
   def main(args: Array[String]) {
      println("文件内容为:" )
			
     	// 1. 
      Source.fromFile("test.txt" ).foreach{ 
         print 
      }
     // 2.返回结果是个迭代器
     Source.fromFile("test.txt" ).getlines 
   }
}

控制结构

条件: if

if(布尔表达式 1){
   // 如果布尔表达式 1 为 true 则执行该语句块
}else if(布尔表达式 2){
   // 如果布尔表达式 2 为 true 则执行该语句块
}else if(布尔表达式 3){
   // 如果布尔表达式 3 为 true 则执行该语句块
}else {
   // 如果以上条件都为 false 执行该语句块
}

循环:While/do…while/for

for( a <- 1 to 10){
	println( "Value of a: " + a );
}

for( a <- 1 to 3; b <- 1 to 3){
 	println( "Value of a: " + a );
	println( "Value of b: " + b );
}

val numList = List(1,2,3,4,5,6);
for( a <- numList ){
  println( "Value of a: " + a );
}

//for 循环过滤
for( a <- numList if a != 3; if a < 8 ){
  println( "Value of a: " + a );
}

//for 使用 yield
var retVal = for{ a <- numList 
                 if a != 3; if a < 8
                }yield a

数据结构

容器(Collection)

  • Scala提供了一套丰富的容器(collection)库,包括列表 (List)、数组(Array)、集合(Set)、映射(Map)等
  • 根据容器中元素的组织方式和操作方式,可以区分为有序 和无序、可变和不可变等不同的容器类别
  • Scala用了三个包来组织容器类,分别是scala.collection 、 scala.collection.mutable(可变集)和scala.collection.immutable(不可变集)
  • 它为所有的容器类定义了公用的foreach 方法,用于对容器元素进行遍历操作

列表(List):

Scala 列表类似于数组,它们所有元素的类型都相同,但是它们也有所不同:列表是不可变的,值一旦被定义了就不能改变,其次列表 具有递归的结构(也就是链接表结构)而数组不是。。

几个要知道的符号:

  • 列表的元素类型 T 可以写成 List[T]
  • 构造列表的两个基本单位是 Nil::Nil 也可以表示为一个空列表。
定义

有两种方式:

// 字符串列表
val site: List[String] = List("Runoob", "Google", "Baidu")
val site = "Runoob" :: ("Google" :: ("Baidu" :: Nil))

// 空列表
val empty: List[Nothing] = List()
val empty = Nil

// 二维列表
val dim: List[List[Int]] =
   List(
      List(1, 0, 0),
      List(0, 1, 0),
      List(0, 0, 1)
   )
val dim = (1 :: (0 :: (0 :: Nil))) ::
          (0 :: (1 :: (0 :: Nil))) ::
          (0 :: (0 :: (1 :: Nil))) :: Nil
列表基本操作
  • head 返回列表第一个元素
  • tail 返回一个列表,包含除了第一元素之外的其他元素
  • isEmpty 在列表为空时返回true
println( "第一网站是 : " + site.head )
println( "最后一个网站是 : " + site.tail )
println( "查看列表 site 是否为空 : " + site.isEmpty )
连接列表

可以使用 ::: 运算符或 List.::😦) 方法或 List.concat() 方法来连接两个或多个列表。

// 使用 ::: 运算符
var fruit = site1 ::: site2
println( "site1 ::: site2 : " + fruit )

// 使用 List.:::() 方法
fruit = site1.:::(site2)
println( "site1.:::(site2) : " + fruit )

// 使用 concat 方法
fruit = List.concat(site1, site2)
println( "List.concat(site1, site2) : " + fruit  )
Scala List 常用方法
  • List.fill(): 我们可以使用 List.fill() 方法来创建一个指定重复数量的元素列表:

    val site = List.fill(3)("Runoob") // 重复 Runoob 3次
    println( "site : " + site  )
    
    val num = List.fill(10)(2)         // 重复元素 2, 10 次
    println( "num : " + num  )
    
  • List.tabulate() 方法是通过给定的函数来创建列表。

    方法的第一个参数为元素的数量,可以是二维的,第二个参数为指定的函数,我们通过指定的函数计算结果并返回值插入到列表中,起始值为 0,实例如下:

    // 通过给定的函数创建 5 个元素
    val squares = List.tabulate(6)(n => n * n)
    println( "一维 : " + squares  )
    
    // 创建二维列表
    val mul = List.tabulate( 4,5 )( _ * _ )      
    println( "多维 : " + mul  )
    

    输出:

    一维 : List(0, 1, 4, 9, 16, 25)
    多维 : List(List(0, 0, 0, 0, 0), List(0, 1, 2, 3, 4), List(0, 2, 4, 6, 8), List(0, 3, 6, 9, 12))
    
// +: 为列表添加元素 (:朝着list)
"xxx"+:site // 返回:List(xxx, Runoob, Google, Baidu) 

// :+ 
site :+ "xxx" // 返回 List[String] = List(Runoob, Google, Baidu, xxx)

// :: 在列表开头添加元素
"xxx"::site  // 返回:List(xxx, Runoob, Google, Baidu)

// :::在列表开头添加指定列表的元素
site ::: nums // val res35: List[Any] = List(Runoob, Google, Baidu, 1, 3, 2)

// ++ 拼接
site++nums  // 返回:val res34: List[Any] = List(Runoob, Google, Baidu, 1, 3, 2)

// ++:和:++
site :++ nums // val res31: List[Any] = List(Runoob, Google, Baidu, 1, 3, 2)
site ++: nums // val res29: List[Any] = List(Runoob, Google, Baidu, 1, 3, 2)

site.apply(2) // apply 通过列表索引获取元素
// val res42: String = Baidu
site.contains("baidu")
// val res43: Boolean = false
val nums = List(1,1,2,3); nums.distinct
// val res45: List[Int] = List(1, 2, 3)
nums.exists(x=>x>1)  // 判断列表中指定条件的元素是否存在。
// val res47: Boolean = true
nums.filter(x=>x>1)  // 输出符号指定条件的所有元素。
//val res48: List[Int] = List(2, 3)
site.foreach(print(_)) // 将函数应用到列表的所有元素
// RunoobGoogleBaidu
site.indexOf("Baidu")
//val res69: Int = 2
site.map(x=>x+"xxx")
// val res71: List[String] = List(Runoobxxx, Googlexxx, Baiduxxx)
site.mkString(";")  // 使用分隔符将列表所有元素作为字符串显示
// val res74: String = Runoob;Google;Baidu
site.mkString  // 列表所有元素作为字符串显示
// val res75: String = RunoobGoogleBaidu
site.reverse
// val res77: List[String] = List(Baidu, Google, Runoob)

site.toString()
// val res86: String = List(Runoob, Google, Baidu)

集合(Set)

  • 集合包括可变集不可变集
  • 默认是不可变的,如果要声明一个可变集,则需要提前引入scala.collection.mutable.Set
import scala.collection.mutable.Set // 可以在任何地方引入 可变集合
val mutableSet = Set(1,2,3)
// val mutableSet: scala.collection.mutable.Set[Int] = HashSet(1, 2, 3)
mutableSet.add(4)
mutableSet.remove(1)

num1 & num2  // 交集 或者.&或.intersect 取交集
// val res97: scala.collection.mutable.Set[Int] = HashSet(20, 9)
num1 &~ num2 // 差集
//val res98: scala.collection.mutable.Set[Int] = HashSet(5, 6, 45, 30)
num2 &~ num1 // 差集
//val res99: scala.collection.mutable.Set[Int] = HashSet(50, 35, 55, 60)

num1 ++ num2 // 连接集合
// val res101: scala.collection.mutable.Set[Int] = HashSet(35, 5, 6, 9, 45, 50, 20, 55, 60, 30)

映射(Map)

  • Map 有两种类型,可变与不可变,区别在于可变对象可以修改它,而不可变对象不可以。
  • 默认情况下 Scala 使用不可变 Map。如果你需要使用可变集合,你需要显式的引入 import scala.collection.mutable.Map
  • 更多参考API
// 空哈希表,键为字符串,值为整型
var A:Map[Char,Int] = Map()

// Map 键值对演示
val colors = Map("red" -> "#FF0000", "azure" -> "#F0FFFF")

println( "colors 中的键为 : " + colors.keys )
println( "colors 中的值为 : " + colors.values )
println( "检测 colors 是否为空 : " + colors.isEmpty )

colors.keys.foreach{ i =>  
   										print( "Key = " + i )
   										println(" Value = " + colors(i) )}
colors.toSet
// val res106: scala.collection.immutable.Set[(String, String)] = Set((red,#FF0000), (azure,#F0FFFF))

迭代器(Iterator)

  • 在Scala中,迭代器(Iterator)不是一个集合,但是,提供了 访问集合的一种方法
  • 迭代器包含两个基本操作:nexthasNext。next可以返回迭代器的下一个元素,hasNext用于检测是否还有下一个元素
val it = Iterator("Baidu", "Google", "Runoob", "Taobao")
      
while (it.hasNext){
      println(it.next())
}
it.size
it.length

数组(Array)

  • 数组是一种可变的、可索引的、元素具有相同类型的数据集合,它是各种高 级语言中最常用的数据结构。
  • Scala提供了参数化类型的通用数组类Array[T], 其中T可以是任意的Scala类型,可以通过显式指定类型或者通过隐式推断来 实例化一个数组。
  • Array提供了函数ofDim来定义二维和三维数组
  • 采用Array类型定义的数组属于定长数组,其数组长度在初始化后就不能改变。如果要定义变长数组,需要使用ArrayBuffer参数类型,其位于包 scala.collection.mutable中。
  • 更多参考
import Array._
// 定义1
var z = Array("Runoob", "Baidu", "Google")
// 定义2
var z = new Array[String](3)
z(0) = "Runoob"; z(1) = "Baidu"; z(4/2) = "Google"
// 输出所有数组元素
for ( x <- myList ) {
  println( x )
}
myList.length

// 多维数组,通过ofDim定义
var myMatrix = ofDim[Int](3,3)    
for (i <- 0 to 2) {
  for ( j <- 0 to 2) {
    myMatrix(i)(j) = j;
  }
}

// 合并数组
var myList3 =  concat( myList1, myList2)

元组(Tuple)

  • 与列表一样,元组也是不可变的,但与列表不同的是元组可以包含不同类型的元素。
  • 目前 Scala 支持的元组最大长度为 22。
  • 我们可以使用 t._1 访问第一个元素, t._2 访问第二个元素
val t = (1, 3.14, "Fred")  
val t = (4,3,2,1)
val sum = t._1 + t._2 + t._3 + t._4  // 访问元祖元素;返回10
t.productIterator.foreach{ i =>println("Value = " + i )} //Tuple.productIterator() 迭代输出元组的所有元素

Option

  • Scala Option(选项)类型用来表示一个值是可选的(有值或无值)。
  • Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None 。
  • 可以使用 getOrElse() 方法来获取元组中存在的元素或者使用其默认的值,
val myMap: Map[String, String] = Map("key1" -> "value")
val value1: Option[String] = myMap.get("key1")  // Some("value1")
val value2: Option[String] = myMap.get("key2")  // None

def show(x: Option[String]) = x match {
      case Some(s) => s
      case None => "?"
   }
print(show(value1) )  // value
print(show(value2) )  // ? 

value1.getOrElse(0) // value
value2.getOrElse(0) // 0

value1.filter(_=="value") 
// val res6: Option[String] = Some(value)

面向对象编程基础

Scala 方法与函数

  • Scala 有方法与函数,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。
  • Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象。
  • Scala 中使用 val 语句可以定义函数,def 语句定义方法。

方法

  • 方法定义由一个 def 关键字开始,紧接着是可选的参数列表,一个冒号 : 和方法的返回类型,一个等于号 = ,最后是方法的主体。
  • 如果方法没有返回值,可以返回为 Unit,这个类似于 Java 的 void,
def functionName ([参数列表]) : [return type]  // 声明

def functionName ([参数列表]) : [return type] = {  // 定义
   function body
   return [expr]
}

// 举例
object Test {
   def main(args: Array[String]) {
        println( "Returned Value : " + addInt(5,7) );
   }
   def addInt( a:Int, b:Int ) : Int = {
      var sum:Int = 0
      sum = a + b

      return sum
   }
}

class Point(xc: Int, yc: Int) {
   var x: Int = xc
   var y: Int = yc

   def move(dx: Int, dy: Int) {
      x = x + dx
      y = y + dy
      println ("x 的坐标点: " + x);
      println ("y 的坐标点: " + y);
   }
  
  def increment():Unit = {x += 1}
  def current(): Int = {value} // 如果操作语句只有一句
}

object Test {
   def main(args: Array[String]) {
      val pt = new Point(10, 20);

      // 移到一个新的位置
      pt.move(10, 10);
   }
}

对象

单例对象

  • Scala并没有提供Java那样的静态方法或静态字段,但是,可以采用 object关键字实现单例对象,具备和Java静态方法同样的功能。

在这里插入图片描述

伴生对象

  • 在Java中,我们经常需要用到同时包含实例方法和静态 方法的类,在Scala中可以通过伴生对象来实现。
  • 当单例对象与某个类具有相同的名称时,它被称为这个 类的“伴生对象”。
  • 类和它的伴生对象必须存在于同一个文件中,而且可以 相互访问私有成员(字段和方法)。

继承

Scala继承一个基类跟Java很相似, 但我们需要注意以下几点:

  • 1、重写一个非抽象方法必须使用override修饰符。
  • 2、只有主构造函数才可以往基类的构造函数里写参数。
  • 3、在子类中重写超类的抽象方法时,不需要使用override关键字。

特质

模式匹配

函数式编程

实例WordCount:

import java.io.File
import scala.io.Source
object WordCount{
  def main(args:Array[String]):Unit={
    val dirfile=new File("wordCount")
    val files = dirfile.listFiles
    for(file <- files) print(file)
    val listFiles = files.toList
    val wordsMap = scala.collection.mutable.Map[String,Int]()
    listFiles.foreach(file => Source.fromFile(file).getLines().foreach(line => line.split(" ").foreach(
      word => {
        if(wordsMap.contains(word)){
          wordsMap(word) += 1
        }else{
          wordsMap+=(word->1)
        }
      }
    )))
  println(wordsMap)
  for((key,value)<-wordsMap) print(key + ": " + value)
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值