Ubuntu环境下使用scala
配置好环境变量后,scala命令下进入Scala解释器。
编译
$ scalac test.scala
运行
$ scala -classpath . test.scala
导包
所有内容不再是*而是_
eg:import io. StdIn._
Range
1 to 10 by 2 (1,3,5,7,9)
读写文件
写:
import java.io.PrintWriter
import java.io.PrintWriter //这行是Scala解释器执行上面语句后返回的结果
scala> val out = new PrintWriter("output.txt")
out: java.io.PrintWriter = java.io.PrintWriter@25641d39 //这行是Scala解释器执行上面语句后返回的结果
scala> for (i <- 1 to 5) out.println(i)
scala> out.close()
存储路径默认是进入scala解释器的路径,最好写绝对路径。
读:
scala> import scala.io.Source
import scala.io.Source //这行是Scala解释器执行上面语句后返回的结果
scala> val inputFile = Source.fromFile("output.txt")
inputFile: scala.io.BufferedSource = non-empty iterator //这行是Scala解释器执行上面语句后返回的结果
scala> val lines = inputFile.getLines //返回的结果是一个迭代器
lines: Iterator[String] = non-empty iterator //这行是Scala解释器执行上面语句后返回的结果
scala> for (line <- lines) println(line)
控制结构
条件
val x = 3
if (x>0) {
println("This is a positive number")
} else if (x==0) {
println("This is a zero")
} else {
println("This is a negative number")
}
可以将表达式的值进行赋值
val x = 6
val a = if (x>0) 1 else -1
循环
里面的表达式称为生成器。
for(i <- 1 to 5)
var i = 9
while (i > 0) {
i -= 1
printf("i is %d\n",i)
}
没有i++这种操作。
多重循环
for (i <- 1 to 5; j <- 1 to 3) println(i*j)
守卫
过滤满足表达式,每个生成器都可以添加守卫。
for (i <- 1 to 5 if i%2==0) println(i)
for推导式
对过滤后的结果需要再次处理,对结果构建一个集合。
val r = for (i <- 1 to 5 if i%2==0) yield i
0 2 4 被保存到r变量中
数据结构
可变与不可变:可变意味着可以在原来的数据结构上进行修改,不可变意味着对修改之后生成的是新的数据结构
数组Array
val myStrArr = new Array[String](3) //声明一个长度为3的字符串数组,每个数组元素初始化为null
myStrArr(0) = "BigData"
访问的时候是()
直接初始化值的时候可以不声明类型更简便。
val intValueArr = Array(12,45,33)
val myStrArr = Array("BigData","Hadoop","Spark")
列表list
同类型不可变。头元素intList.head,尾元素依然是个列表(除头元素外)intList.tail
val intList = List(1,2,3)
val intListOther = 0::intList
元素与列表连接
val intListOther = 0::intList
列表连接
val intList3 = intList1:::intList2
元组Tuple
不同类型
val tuple = ("BigData",2015,45.0)
tuple._1 //BigData
访问使用tuple._1这种格式
集合Set
不同类型无序,通常使用不可变
var mySet = Set("Hadoop","Spark")
映射Map
val university2 = Map("XMU" -> "Xiamen University", "THU" -> "Tsinghua University","PKU"->"Peking University")
遍历
for ((k,v) <- university) printf("Code is : %s and name is: %s\n",k,v)
for (k<-university.keys) println(k)
迭代器
val iter = Iterator("Hadoop","Spark","Scala")
while (iter.hasNext) {
println(iter.next())
}
类
Unit是返回值类型相当于void,返回值最后一个表达式是相当于return语句。
class Counter {
private var name = "" //表示计数器的名称
private var mode = 1 //mode用来表示计数器类型(比如,1表示步数计数器,2表示时间 计数器)
def this(name: String){ //第一个辅助构造器
this() //调用主构造器
this.name = name
}
def this (name: String, mode: Int){ //第二个辅助构造器
this(name) //调用前一个辅助构造器
this.mode = mode
}
private var privateValue = 0
//类似Java的getter setter
def value = privateValue //定义一个方法,方法的名称就是原来我们想要的字段的名称
def value_=(newValue: Int){
if (newValue > 0) privateValue = newValue //只有提供的新值是正数,才允许修改
}
def increment(): Unit = { privateValue += 1}
def current(): Int = {privateValue }
}
辅助构造必须调用前一个辅助构造或者主构造。
主构造函数需写在类名后面,默认是无参
class Counter(val name: String, val mode: Int) {}
抽象类
abstract class Car{ //是抽象类,不能直接被实例化
val carBrand: String //字段没有初始化值,就是一个抽象字段
def info() //抽象方法,不需要使用abstract关键字
def greeting() {println("Welcome to my car!")}
}
继承
实现具体方法要override,抽象方法不加,重写字段要加。
class BMWCar extends Car {
override val carBrand = "BMW" //重写超类字段,需要使用override关键字,否则编译会报错
def info() {printf("This is a %s car. It is on sale", carBrand)} //重写超类的抽象方法时,不需要使用override关键字,不过,如果加上override编译也不错报错
override def greeting() {println("Welcome to my BMW car!")} //重写超类的非抽象方法,必须使用override关键字
}
特质
类似于接口,但可以有具体实现,trait关键字
trait CarId{
var id: Int
def currentId(): Int //定义了一个抽象方法
}
class BYDCarId extends CarId{ //使用extends关键字
override var id = 10000 //BYD汽车编号从10000开始
def currentId(): Int = {id += 1; id} //返回汽车编号
}
模式匹配
类似于 switch
val colorNum = 4
val colorStr = colorNum match {
case 1 => "red"
case 2 => "green"
case 3 => "yellow"
case unexpected => unexpected + " is Not Allowed"
}
println(colorStr)
适用于类的匹配,类型的匹配
//类型判断
for (elem <- List(9,12.3,"Spark","Hadoop",'Hello)){
val str = elem match{
case i: Int => i + " is an int value."
case d: Double => d + " is a double value."
case "Spark"=> "Spark is found."
case s: String => s + " is a string value."
case _ => "This is an unexpected value."
}
println(str)
}
//加入表达式判断
for (elem <- List(1,2,3,4)){
elem match {
case _ if (elem %2 == 0) => println(elem + " is even.")
case _ => println(elem + " is odd.")
}
}
case class Car(brand: String, price: Int)
val myBYDCar = new Car("BYD", 89000)
val myBMWCar = new Car("BMW", 1200000)
val myBenzCar = new Car("Benz", 1500000)
for (car <- List(myBYDCar, myBMWCar, myBenzCar)) {
car match{
case Car("BYD", 89000) => println("Hello, BYD!")
case Car("BMW", 1200000) => println("Hello, BMW!")
case Car(brand, price) => println("Brand:"+ brand +", Price:"+price+", do you want it?")
}
}
函数式编程
函数类型和函数值
函数类型:抽取参数类型和返回类型
函数值:去掉函数定义中的函数声明
def counter(value: Int): Int = { value += 1}
//函数类型
(Int) => Int
//函数值
(value) => {value += 1} //只有一条语句时,大括号可以省略
声明函数
val counter: (Int) => Int = { (value) => value +=1 }
匿名函数(Lambda表达式)
(num: Int) => num * 2
//函数声明,匿名函数
var myFunc:Int => Int = (num:Int) => num * 2
myFunc(5)//10
集合操作
map
将某个函数应用到集合中的每个元素,并产生一个结果集合
scala> val books = List("Hadoop", "Hive", "HDFS")
books: List[String] = List(Hadoop, Hive, HDFS)
scala> books.map(s => s.toUpperCase)
res0: List[String] = List(HADOOP, HIVE, HDFS)
flatMap
该函数对每个输入都会返回一个集合(而不是一个元素),然后,flatMap把生成的多个集合“拍扁”成为一个集合。
hadoop输入,返回的是List(h,a,d,o,o,p) 类似的剩余元素也各返回一个集合,拍扁三个集合得到最终结果
scala> val books = List("Hadoop","Hive","HDFS")
books: List[String] = List(Hadoop, Hive, HDFS)
scala> books flatMap (s => s.toList)
res0: List[Char] = List(H, a,d, o, o, p, H, i, v, e, H, D, F, S)
filter
过滤操作
val u = university.filter {kv => kv._2 contains "Xiamen"}
reduce
对集合中的元素进行归约
scala> val list = List(1,2,3,4,5)
list: List[Int] = List(1, 2, 3, 4, 5)
scala> list.reduceLeft(_ + _)
res21: Int = 15
scala> list.reduceRight(_ + _)
res22: Int = 15
fold
需要从一个初始的“种子”值开始,并以该值作为上下文,处理集合中的每个元素
scala> val list = List(1,2,3,4,5)
list: List[Int] = List(1, 2, 3, 4, 5)
scala> list.fold(10)(_*_)
res0: Int = 1200
函数式编程实例WordCount
词频统计
import java.io.File
import scala.io.Source
object WordCount {
def main(args: Array[String]): Unit = {
val dirfile=new File("/usr/local/scala/mycode/wordcount")
val files=dirfile.listFiles
for(file <- files) println(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) println(key+": "+value)
}
}