scala 集合
集合分为可变和不可变的,不可变是指像String 那样。会新开辟一个引用存放变化后的集合,而不会覆盖旧的的集合。
mutable and immutable 可变和不可变。
Array
不可变:Array具备很多集合操作,向左/右追加: +:;直接求最大/最小/求和等方法
- 创建数组一:使用new 定义:指定类型、长度
val strings = new Array[String](5)
- 创建数组二:new Array(5)。没有指定类型, 自动推测的类型是 Nothing 不是NUll。 Nothing在Scala是所有类型的子类
val array: Array[Nothing] = new Array(5)
- 创建数组三:Array(1,2,3,4,5) ,底层是使用Array的 apply()方法
val applyArr = Array(1,2,3,4,5)
赋值或读取数组的内容,用(index)获取指定索引的值。
strings(0) = "A"
strings.update(1,"B")
println(strings(0))
// 获取数组的长度
val length = strings.length
println("长度:"+length)
// 往左/右 追加数据
val array1 = strings :+ "C"
// val array1 = strings +: "C"
array1.foreach(e =>println(e))
// 数组转String,分隔符可选
val str = strings.mkString(",")
println(str)
// 最值\求和...
val max = applyArr.max
val sum = applyArr.sum
可变:ArrayBuffer,仍然集合的操作方法。但追加后可以再赋值给旧集合,所以追加是: +=:
val arrayBuffer = new ArrayBuffer[String]()
arrayBuffer.insert(1,"c")
arrayBuffer.remove(0,1) // 移除索引 [0,1)的元素
arrayBuffer.foreach(println(_))
"d" +=: arrayBuffe
可变集合与不可变集合之间可以互转。
val buffer: mutable.Buffer[String] = array.toBuffer
val array: Array[String] = arrayBuffer.toArray
Lsit
Nil 表示空的List ,即List()
println(Nil == List()) // true
定义一个List
- List(1, 2, 3, 4, 5)
val list = List(1, 2, 3, 4, 5)
println(list.head)
// 除了 head 的元素都是 tail ,tail并不是最后一个
val tail = list.tail
- List(1,2,3) 也可以写成 1 :: 2 :: 3 :: Nil
val ints: List[Int] = 1 :: 2 :: 3 :: Nil
源码知:有一个case class 就叫 ::
- 而 ::: 可以合并两个集合
val list2 = ints ::: list
list.reverse 将集合反转
list.head 取集合第一个元素
list.tail 返回集合中第二个到最后一个元素组成的新集合
…
交、并、差集
List 有序可重复,Set 无序不重复。对应Java 的ArrayList 、HashSet
Tuple (元组)
Tuple 定义方式一
val tuple = (1, 2, 3, 4)
Tuple 定义 :TupleN,固定长度
val tuple1 = Tuple3("A", "B", "C")
Tuple 定义 key -> value
// val tuple = "key" -> "value" 等同于 val tuple = ("key","value")
val tuple2: (Int, String) = 0 -> "a"
val tuple3: ((Int, String), String) = 0 -> "a" -> "A" // 嵌套的 Tuple
取 (注意从1开始,不是从0了)
tuple._1
tuple._2
tuple._3
tuple._4
val value = tuple3._1._2 // 取第一个元素里的第二个元素
遍历
for (i <- t.productIterator){
println(i) // 获取的是元素
}
只有两个元素的Tuple(嵌套的)可以实现Json的数据结构 。叫对偶,对偶可以交换两个元素顺序
Array、List和Tuple 区别
Array中的元素值可变,List和Tuple中的元素值不可变。
Array和List中的元素类型必须相同,Tuple可以存放不同的元素类型。
Array通常是先定长度后赋值,而List和Tuple在声明的时候就要赋值。
Array取单个元素的复杂度是O(1)。而List读取单个元素的复杂度是O(n).
Array和List声明时不需要new,而Tuple有无new都可以。
Array、List都是从下标0开始访问,形式为Array(0)、List(0),而Tuple从下标1开始访问,形式为Tuple._1
——
Scala中Array、List和Tuple三者差别:https://blog.csdn.net/qq_17310871/article/details/100785486
Map
Map定义
val map: Map[String, Any] = Map("age" -> 20, "name" -> "pk")
遍历
map.foreach(println(_))
// 或
for ( e <- map){
println(e)
}
// 只遍历 keys、或只遍历 values
for ( e <- map.keys){
println(e)
}
val tuple = Tuple2(("age" -> 20), ("name" -> "pk"))
for (i <- tuple.productIterator){
println(i) // 打印出的结构和内容 与上述 map一致
}
可以直接操作,也可以get(),但推荐使用 getOrElse()
val value = map("age")
val option = map.get("age")
val value2 = option.get // 可能会空指针
val value3 = map.getOrElse("age", 0)
// 可变的map
val map1 = scala.collection.mutable.Map("age" -> 20, "name" -> "pk")
添加和删除
map.put("gender","男") // 按提示导包
map -= "gender"
Map 是有序的,与添加的元素顺序一致。 更像是LinkedHashMap(有序)而不是HashMap(无序)。
sorMap() , 无序。添加的元素会被sorMap重排序。底层是 TreeMap(无序,自然排序)。
Queue 队列
val queue = scala.collection.mutable.Queue[Int]()
获取第一个元素:queue.head
取出第一个元素(并将队列中这个元素删除):queue.dequeue(1,2,3)
添加元素到队列(只能添加到最后): queue.enqueue(4)
获取tail (除了 head 都是tail):queue.tail
Stack 栈
val stack = scala.collection.mutable.Stack[Int](1,2,3)
移除头部元素:stack.pop() // 底层是 获取stack.head,同时将stack.tail 重新赋值给stack
方法和函数的定义 (scala05)
方法定义: def fun(a:Int,b:String):Int = {}
def test01(a:Int,b:String): String ={
println("我是一个方法")
a + b
}
函数定义: val fun:(参数类型,参数类型) => 返回值类型 = (a,b) => {函数体} ;
简写为:val fun = (a:Int,b:String) => {}
val fun:(String,String) => String = (a,b) => { a + b }
简写为:
val fun = (a:String,b:String) => {a + b}
函数和方法可以转换,把方法名赋值给一个函数 , 加个 _
val fun2 = test01 _
高阶函数
函数定义甚至可以将Option作为参数传入,也就是方法体需要传入 。函数式编程的支持。
// 只定义了操作数10和20,但具体的操作option需要作为参数传入,实现不同功能
val fun = (option:(Int,Int)=>Int) => {option(10,20)}
传option,也就是说要传一个方法体,传一个执行逻辑体
对fun高阶函数,可以这样调用,三个写法是一样的
fun((a:Int,b:Int)=>a+b)
fun((a,b)=>a+b)
fun(_ + _) // _ 对于“每一个参数”只能使用一次
当然也可以参数和方法体都不定义,都作为参数传入:
def calculator (a:Int,b:Int,op:(Int,Int) => Int): Int ={
op(a,b)
}
调用:传入参数a,b 和一个匿名函数作为op
val i = calculator(1, 2, (a, b) => { a + b })
// (当然更可以将需要的op函数也创建好直接拿来使用)
val add =(a:Int,b:Int) => {a+b}
val ii = calculator(1, 2, add)
柯里化 Currying
将参数定义最小粒度化,调用是也是分开传入。
fun(1)("Hello")
柯理化(currying)可以解决重复传参的问题,并提高函数功能的适用性。后续再补充。
函数式编程
map
将集合map后,传入option对每个元素执行这个option
// list中每个元素乘2倍
val list2 = list.map((e) => e * 2)
val list2 = list.map(e => e * 2)
val list2 = list.map(_ * 2)
val anyList = List(1, "2", 3, true, "zhangsan")
val ints = anyList.filter(_.isInstanceOf[Int])
.map(_.asInstanceOf[Int])
.map(_ * 10)
flatMap 和 map 的区别不在于option的写法,而是在于 flatMap的结果是打扁的,是打乱了原集合的数据结构的,但map返回原来的结构。
用scala写wc的分词
方法一:list.map(.split(“,”)).flatten.map(x =>(x,1)) …
方法二:list.flatmap(.split(“,”)).map(x => (x,1))
reduce
reduce 的op 是要将两个参数,返回一个值。- - 规约,减少:将两两数据按传入的逻辑做规约为一个数。
val sum = list.reduce((a, b) => a + b)
// val sum = list.reduce(_ + _)
// val sum = list.sum
reduceLeft 和 reduceRight 分别表示从左、右依次两两操作。
fold:带初始值的reduce,也有foldLeft 和 foldRight
val i = list.fold(1)(_ + _) // 柯里化
map : 映射。一个元素映射一个结果,一得一
reduce : 规约。两元素规约到一个结果,两得一
用scala写wc,尝试用reduce做统计
未实现。解决不了 a == b 为 false时,如何继续返回。
val listTuple = List("A", "B", "C", "A", "B","B")
val tuple: (String, Int) = listTuple.map(x => (x, 1))
.reduce((a, b) => {
if (a == b) {
(a._1, a._2 + b._2)
}
// else a // 处理不好 else 后返回什么。就算 else a 则结果只能实现对第一个元素求wc
})
groupBy
groupBy 分组,分组后是按条件作为Map的key,满足条件的内容(保持原数据结构)作为value
分组条件可以是自定义的,也可以按元素的内容直接分组(如元素是Tuple)按tuple第一个元素分组:
groupBy(_._1)
组内的类型不会改变,还是分组前的类型 List。
按自定义条件分组:
list.groupBy(x => if (x % 2 == 0) "偶数" else "奇数")
输出:Map(奇数 -> List(1, 3, 5), 偶数 -> List(2, 4))
用scala写wc,可以用group做统计
val listTuple = List("A", "B", "C", "A", "B","B")
val mapTuple = listTuple.map(x => (x, 1)).groupBy(_._1).map(x => (x._1, x._2.length))
// 或
// listTuple.groupBy(x=>x) // Map(A -> List(A, A), B -> List(B, B, B), C -> List(C))
val mapTuple = listTuple.groupBy(x => x).mapValues(_.length)
排序
sortBy 多个排序条件也写到 => (条件) 里
val list1 = list.sortBy(x => -x) // 符号可以降序 等同于: list.sortBy(-_)
list.sortBy(x => x)(Ordering.Int.reverse) // 柯里化实现降序
sorted
sortWith
zip
将两个list对位拉拢合并为一个Tuple类型的list。每个元素变成Tuple(左边元素,右边元素)。
只能拉交集长度的,超过的部分会被舍弃。如果不舍弃的话要用 zipAll
take
TopN问题,取最* 的 *个元素
toList.sortBy(_._1).take(2) // 取前2个
利用高阶函数自定义实现以上算子 (scala06)
注意下 reduce实现两两操作。
思路:
- 取出索引0位元素 array(0) 作为 first,再从索引1开始遍历 array
- 对first 与 array(i) 两元素执行 option,再赋值给first 进行下一次循环
- 最后返回 first
代码:
def reduce(array: Array[Int],option:(Int,Int)=> Int) ={
var first = array(0)
for (i <- 1 until array.length){
first = option(first,array(i))
}
first
}
调用: val i = reduce(Array(0, 1, 2, 3), (_ + _))
文件读写
// 从磁盘读取
val source: BufferedSource = Source.fromFile("data/wc.txt")
for (e <- source.getLines()){
println(e)
}
// 从网络读取
Soruce.fromURL()
lazy
真正用到时才去读取
lazy val source = Source.fromFile("data/wc.txt")
操作 MySql
导入mysql 驱动
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
代码
val url = "jdbc:mysql://Gargantua:9965/jepsondb"
val user = "armsdata"
val password = "123456"
var connection: Connection = null
var pstmt: PreparedStatement = null
var rs: ResultSet = null
try {
classOf[com.mysql.jdbc.Driver]
// 获取连接
connection = DriverManager.getConnection(url, user, password)
// 语
pstmt = connection.prepareStatement("select * from emp")
// 执行
rs = pstmt.executeQuery()
while (rs.next()) {
val empno = rs.getInt("empno")
val ename = rs.getString("ename")
println(s"$empno ==> $ename")
}
} catch {
case e: Exception => e.printStackTrace()
// 释放资源
} finally {
if (null != rs) rs.close()
if (null != pstmt) pstmt.close()
if (null != connection) connection.close()
}
模式匹配
变量 match {
case 值1 => ...
case 值2 => ...
...
case _ => ... // default
}
基础使用,根据内容匹配
val a = 6
val b = 2
val op = StdIn.readLine("请输入运算符:")
val result = op match {
case "+" => a + b
case "-" => a - b
case "*" => a * b
case "/" => a / b
case _ => -99
}
根据数据类型匹配
def matchType(obj:Any) = obj match {
case x:Int if x >15 => println(x + "==>" + (x + 100))
case x:Int => println("int")
case x:Boolean => println(x + "==> boolean")
case x:String => println(x + "==>" + x.toUpperCase)
case x:Map[_,_] => println("map")
case _ => println("other ...")
}
matchType(1)
数组/集合 的部分内容 匹配
val a = Array(100,200,300,400)
a match {
case Array(100,200, other@_*) => println(other.toList)
}
根据Tuple内元素的数据类型匹配
val t = ("小徐",30)
t match {
case (name:String,age) =>
println(name + "==>" + age)
}
class 匹配 : 匹配对象是否属于某类
底层会调用该class对应的伴生对象object中的unapply,没有的话要自行创建
class User(val name:String, val age:Int)
object User {
def unapply(user: User): Option[(String, Int)] = {
if(user != null ) {
Some(user.name, user.age)
} else {
None
}
}
}
val user = new User("小徐", 80)
user match {
case User(name, age) => println(name + " , " + age)
case _ =>
}
case class匹配 : 匹配对象是否属于某类
直接使用 case class 。最好的用法
case class Person(name:String, age:Int)
val person = Person("小徐", 80)
person match {
case Person(name, age) => println(name + " , " + age)
}
偏函数
与模式匹配相关
函数中值偏向部分内容做处理,利用模式匹配对case 满足的内容处理即可。
异常处理
与模式匹配相关
异常依次捕获,利用模式匹配依次 case即可。
scala 集合
集合分为可变和不可变的,不可变是指像String 那样。会新开辟一个引用存放变化后的集合,而不会覆盖旧的的集合。
mutable and immutable 可变和不可变。
Array
不可变:Array具备很多集合操作,向左/右追加: +:;直接求最大/最小/求和等方法
- 创建数组一:使用new 定义:指定类型、长度
val strings = new Array[String](5)
- 创建数组二:new Array(5)。没有指定类型, 自动推测的类型是 Nothing 不是NUll。 Nothing在Scala是所有类型的子类
val array: Array[Nothing] = new Array(5)
- 创建数组三:Array(1,2,3,4,5) ,底层是使用Array的 apply()方法
val applyArr = Array(1,2,3,4,5)
赋值或读取数组的内容,用(index)获取指定索引的值。
strings(0) = "A"
strings.update(1,"B")
println(strings(0))
// 获取数组的长度
val length = strings.length
println("长度:"+length)
// 往左/右 追加数据
val array1 = strings :+ "C"
// val array1 = strings +: "C"
array1.foreach(e =>println(e))
// 数组转String,分隔符可选
val str = strings.mkString(",")
println(str)
// 最值\求和...
val max = applyArr.max
val sum = applyArr.sum
可变:ArrayBuffer,仍然集合的操作方法。但追加后可以再赋值给旧集合,所以追加是: +=:
val arrayBuffer = new ArrayBuffer[String]()
arrayBuffer.insert(1,"c")
arrayBuffer.remove(0,1) // 移除索引 [0,1)的元素
arrayBuffer.foreach(println(_))
"d" +=: arrayBuffe
可变集合与不可变集合之间可以互转。
val buffer: mutable.Buffer[String] = array.toBuffer
val array: Array[String] = arrayBuffer.toArray
Lsit
Nil 表示空的List ,即List()
println(Nil == List()) // true
定义一个List
- List(1, 2, 3, 4, 5)
val list = List(1, 2, 3, 4, 5)
println(list.head)
// 除了 head 的元素都是 tail ,tail并不是最后一个
val tail = list.tail
- List(1,2,3) 也可以写成 1 :: 2 :: 3 :: Nil
val ints: List[Int] = 1 :: 2 :: 3 :: Nil
源码知:有一个case class 就叫 ::
- 而 ::: 可以合并两个集合
val list2 = ints ::: list
list.reverse 将集合反转
list.head 取集合第一个元素
list.tail 返回集合中第二个到最后一个元素组成的新集合
…
交、并、差集
List 有序可重复,Set 无序不重复。对应Java 的ArrayList 、HashSet
Tuple (元组)
Tuple 定义方式一
val tuple = (1, 2, 3, 4)
Tuple 定义 :TupleN,固定长度
val tuple1 = Tuple3("A", "B", "C")
Tuple 定义 key -> value
// val tuple = "key" -> "value" 等同于 val tuple = ("key","value")
val tuple2: (Int, String) = 0 -> "a"
val tuple3: ((Int, String), String) = 0 -> "a" -> "A" // 嵌套的 Tuple
取 (注意从1开始,不是从0了)
tuple._1
tuple._2
tuple._3
tuple._4
val value = tuple3._1._2 // 取第一个元素里的第二个元素
遍历
for (i <- t.productIterator){
println(i) // 获取的是元素
}
只有两个元素的Tuple(嵌套的)可以实现Json的数据结构 。叫对偶,对偶可以交换两个元素顺序
Array、List和Tuple 区别
Array中的元素值可变,List和Tuple中的元素值不可变。
Array和List中的元素类型必须相同,Tuple可以存放不同的元素类型。
Array通常是先定长度后赋值,而List和Tuple在声明的时候就要赋值。
Array取单个元素的复杂度是O(1)。而List读取单个元素的复杂度是O(n).
Array和List声明时不需要new,而Tuple有无new都可以。
Array、List都是从下标0开始访问,形式为Array(0)、List(0),而Tuple从下标1开始访问,形式为Tuple._1
——
Scala中Array、List和Tuple三者差别:https://blog.csdn.net/qq_17310871/article/details/100785486
Map
Map定义
val map: Map[String, Any] = Map("age" -> 20, "name" -> "pk")
遍历
map.foreach(println(_))
// 或
for ( e <- map){
println(e)
}
// 只遍历 keys、或只遍历 values
for ( e <- map.keys){
println(e)
}
val tuple = Tuple2(("age" -> 20), ("name" -> "pk"))
for (i <- tuple.productIterator){
println(i) // 打印出的结构和内容 与上述 map一致
}
可以直接操作,也可以get(),但推荐使用 getOrElse()
val value = map("age")
val option = map.get("age")
val value2 = option.get // 可能会空指针
val value3 = map.getOrElse("age", 0)
// 可变的map
val map1 = scala.collection.mutable.Map("age" -> 20, "name" -> "pk")
添加和删除
map.put("gender","男") // 按提示导包
map -= "gender"
Map 是有序的,与添加的元素顺序一致。 更像是LinkedHashMap(有序)而不是HashMap(无序)。
sorMap() , 无序。添加的元素会被sorMap重排序。底层是 TreeMap(无序,自然排序)。
Queue 队列
val queue = scala.collection.mutable.Queue[Int]()
获取第一个元素:queue.head
取出第一个元素(并将队列中这个元素删除):queue.dequeue(1,2,3)
添加元素到队列(只能添加到最后): queue.enqueue(4)
获取tail (除了 head 都是tail):queue.tail
Stack 栈
val stack = scala.collection.mutable.Stack[Int](1,2,3)
移除头部元素:stack.pop() // 底层是 获取stack.head,同时将stack.tail 重新赋值给stack
方法和函数的定义 (scala05)
方法定义: def fun(a:Int,b:String):Int = {}
def test01(a:Int,b:String): String ={
println("我是一个方法")
a + b
}
函数定义: val fun:(参数类型,参数类型) => 返回值类型 = (a,b) => {函数体} ;
简写为:val fun = (a:Int,b:String) => {}
val fun:(String,String) => String = (a,b) => { a + b }
简写为:
val fun = (a:String,b:String) => {a + b}
函数和方法可以转换,把方法名赋值给一个函数 , 加个 _
val fun2 = test01 _
高阶函数
函数定义甚至可以将Option作为参数传入,也就是方法体需要传入 。函数式编程的支持。
// 只定义了操作数10和20,但具体的操作option需要作为参数传入,实现不同功能
val fun = (option:(Int,Int)=>Int) => {option(10,20)}
传option,也就是说要传一个方法体,传一个执行逻辑体
对fun高阶函数,可以这样调用,三个写法是一样的
fun((a:Int,b:Int)=>a+b)
fun((a,b)=>a+b)
fun(_ + _) // _ 对于“每一个参数”只能使用一次
当然也可以参数和方法体都不定义,都作为参数传入:
def calculator (a:Int,b:Int,op:(Int,Int) => Int): Int ={
op(a,b)
}
调用:传入参数a,b 和一个匿名函数作为op
val i = calculator(1, 2, (a, b) => { a + b })
// (当然更可以将需要的op函数也创建好直接拿来使用)
val add =(a:Int,b:Int) => {a+b}
val ii = calculator(1, 2, add)
柯里化 Currying
将参数定义最小粒度化,调用是也是分开传入。
fun(1)("Hello")
柯理化(currying)可以解决重复传参的问题,并提高函数功能的适用性。后续再补充。
函数式编程
map
将集合map后,传入option对每个元素执行这个option
// list中每个元素乘2倍
val list2 = list.map((e) => e * 2)
val list2 = list.map(e => e * 2)
val list2 = list.map(_ * 2)
val anyList = List(1, "2", 3, true, "zhangsan")
val ints = anyList.filter(_.isInstanceOf[Int])
.map(_.asInstanceOf[Int])
.map(_ * 10)
flatMap 和 map 的区别不在于option的写法,而是在于 flatMap的结果是打扁的,是打乱了原集合的数据结构的,但map返回原来的结构。
用scala写wc的分词
方法一:list.map(.split(“,”)).flatten.map(x =>(x,1)) …
方法二:list.flatmap(.split(“,”)).map(x => (x,1))
reduce
reduce 的op 是要将两个参数,返回一个值。- - 规约,减少:将两两数据按传入的逻辑做规约为一个数。
val sum = list.reduce((a, b) => a + b)
// val sum = list.reduce(_ + _)
// val sum = list.sum
reduceLeft 和 reduceRight 分别表示从左、右依次两两操作。
fold:带初始值的reduce,也有foldLeft 和 foldRight
val i = list.fold(1)(_ + _) // 柯里化
map : 映射。一个元素映射一个结果,一得一
reduce : 规约。两元素规约到一个结果,两得一
用scala写wc,尝试用reduce做统计
未实现。解决不了 a == b 为 false时,如何继续返回。
val listTuple = List("A", "B", "C", "A", "B","B")
val tuple: (String, Int) = listTuple.map(x => (x, 1))
.reduce((a, b) => {
if (a == b) {
(a._1, a._2 + b._2)
}
// else a // 处理不好 else 后返回什么。就算 else a 则结果只能实现对第一个元素求wc
})
groupBy
groupBy 分组,分组后是按条件作为Map的key,满足条件的内容(保持原数据结构)作为value
分组条件可以是自定义的,也可以按元素的内容直接分组(如元素是Tuple)按tuple第一个元素分组:
groupBy(_._1)
组内的类型不会改变,还是分组前的类型 List。
按自定义条件分组:
list.groupBy(x => if (x % 2 == 0) "偶数" else "奇数")
输出:Map(奇数 -> List(1, 3, 5), 偶数 -> List(2, 4))
用scala写wc,可以用group做统计
val listTuple = List("A", "B", "C", "A", "B","B")
val mapTuple = listTuple.map(x => (x, 1)).groupBy(_._1).map(x => (x._1, x._2.length))
// 或
// listTuple.groupBy(x=>x) // Map(A -> List(A, A), B -> List(B, B, B), C -> List(C))
val mapTuple = listTuple.groupBy(x => x).mapValues(_.length)
排序
sortBy 多个排序条件也写到 => (条件) 里
val list1 = list.sortBy(x => -x) // 符号可以降序 等同于: list.sortBy(-_)
list.sortBy(x => x)(Ordering.Int.reverse) // 柯里化实现降序
sorted
sortWith
zip
将两个list对位拉拢合并为一个Tuple类型的list。每个元素变成Tuple(左边元素,右边元素)。
只能拉交集长度的,超过的部分会被舍弃。如果不舍弃的话要用 zipAll
take
TopN问题,取最* 的 *个元素
toList.sortBy(_._1).take(2) // 取前2个
利用高阶函数自定义实现以上算子 (scala06)
注意下 reduce实现两两操作。
思路:
- 取出索引0位元素 array(0) 作为 first,再从索引1开始遍历 array
- 对first 与 array(i) 两元素执行 option,再赋值给first 进行下一次循环
- 最后返回 first
代码:
def reduce(array: Array[Int],option:(Int,Int)=> Int) ={
var first = array(0)
for (i <- 1 until array.length){
first = option(first,array(i))
}
first
}
调用: val i = reduce(Array(0, 1, 2, 3), (_ + _))
文件读写
// 从磁盘读取
val source: BufferedSource = Source.fromFile("data/wc.txt")
for (e <- source.getLines()){
println(e)
}
// 从网络读取
Soruce.fromURL()
lazy
真正用到时才去读取
lazy val source = Source.fromFile("data/wc.txt")
操作 MySql
导入mysql 驱动
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
代码
val url = "jdbc:mysql://Gargantua:9965/jepsondb"
val user = "armsdata"
val password = "123456"
var connection: Connection = null
var pstmt: PreparedStatement = null
var rs: ResultSet = null
try {
classOf[com.mysql.jdbc.Driver]
// 获取连接
connection = DriverManager.getConnection(url, user, password)
// 语
pstmt = connection.prepareStatement("select * from emp")
// 执行
rs = pstmt.executeQuery()
while (rs.next()) {
val empno = rs.getInt("empno")
val ename = rs.getString("ename")
println(s"$empno ==> $ename")
}
} catch {
case e: Exception => e.printStackTrace()
// 释放资源
} finally {
if (null != rs) rs.close()
if (null != pstmt) pstmt.close()
if (null != connection) connection.close()
}
模式匹配
变量 match {
case 值1 => ...
case 值2 => ...
...
case _ => ... // default
}
基础使用,根据内容匹配
val a = 6
val b = 2
val op = StdIn.readLine("请输入运算符:")
val result = op match {
case "+" => a + b
case "-" => a - b
case "*" => a * b
case "/" => a / b
case _ => -99
}
根据数据类型匹配
def matchType(obj:Any) = obj match {
case x:Int if x >15 => println(x + "==>" + (x + 100))
case x:Int => println("int")
case x:Boolean => println(x + "==> boolean")
case x:String => println(x + "==>" + x.toUpperCase)
case x:Map[_,_] => println("map")
case _ => println("other ...")
}
matchType(1)
数组/集合 的部分内容 匹配
val a = Array(100,200,300,400)
a match {
case Array(100,200, other@_*) => println(other.toList)
}
根据Tuple内元素的数据类型匹配
val t = ("小徐",30)
t match {
case (name:String,age) =>
println(name + "==>" + age)
}
class 匹配 : 匹配对象是否属于某类
底层会调用该class对应的伴生对象object中的unapply,没有的话要自行创建
class User(val name:String, val age:Int)
object User {
def unapply(user: User): Option[(String, Int)] = {
if(user != null ) {
Some(user.name, user.age)
} else {
None
}
}
}
val user = new User("小徐", 80)
user match {
case User(name, age) => println(name + " , " + age)
case _ =>
}
case class匹配 : 匹配对象是否属于某类
直接使用 case class 。最好的用法
case class Person(name:String, age:Int)
val person = Person("小徐", 80)
person match {
case Person(name, age) => println(name + " , " + age)
}
偏函数
与模式匹配相关
函数中值偏向部分内容做处理,利用模式匹配对case 满足的内容处理即可。
异常处理
与模式匹配相关
异常依次捕获,利用模式匹配依次 case即可。
特殊于Java的总结
scala 的for 循环可以有返回值,通过使用yield
val result = for(i <- 1 to 10) {yield i * i}
可变参数的写法
定义
// 可变参数,放在参数最后一位
def mothod(nums:Int*): Unit ={
// ...
}
调用
mothod(1,2,3,4,5)
// 特殊语法也能调用。 :_* 来标识
mothod(1 to 5:_*)
mothod(Array(1,2,3,4,5):_*)
java / scala 混合编程、隐式转换
// 过时的版本. scala 2.12前
import scala.collection.JavaConversions._
for(e <- list){}
// 源码提示导入JavaConverters,但是使用时需要加上 .asScala
import scala.collection.JavaConverters._
// 并且 list需要显示转换为scala
for(e <- list.asScala){}
// _是一个占位符
// Spark SQL 的时候也有个_
import spark.implicits._
// flink 的时候也有个_
import org.apache.flink.api.scala._