scala 学习【二】

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实现两两操作。

思路:

  1. 取出索引0位元素 array(0) 作为 first,再从索引1开始遍历 array
  2. 对first 与 array(i) 两元素执行 option,再赋值给first 进行下一次循环
  3. 最后返回 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实现两两操作。

思路:

  1. 取出索引0位元素 array(0) 作为 first,再从索引1开始遍历 array
  2. 对first 与 array(i) 两元素执行 option,再赋值给first 进行下一次循环
  3. 最后返回 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._

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《快学Scala PDF第版》是一本非常实用的Scala编程入门指南。本书涵盖了Scala的基本概念、核心语法、函数式编程、面向对象编程、并发编程等多个方面的内容,适合初学者和有一定编程基础的读者阅读。 本书第一部分介绍了Scala的基本概念和语法,包括变量、数据类型、函数、类和对象等内容,帮助读者快速入门并掌握Scala的基础知识。第部分介绍了Scala的函数式编程特性,包括高阶函数、匿名函数、闭包等,帮助读者理解函数式编程的思想和应用。第三部分介绍了Scala的面向对象编程特性,包括类的定义、继承、多态等,帮助读者掌握面向对象编程的基本原理和技巧。第四部分介绍了Scala的并发编程特性,包括并发基础、线程、并发集合等,帮助读者理解并发编程的概念和应用。 本书还通过大量实例和案例帮助读者加深对Scala的理解和掌握,让读者能够通过实际练习提升编程能力。此外,本书还介绍了Scala的一些高级特性和应用场景,如模式匹配、解构、隐式转换等,帮助读者更深入地学习和应用Scala编程语言。 总的来说,《快学Scala PDF第版》是一本很不错的Scala编程入门书籍,内容丰富、通俗易懂,适合广大学习者阅读。希望读者能够通过阅读本书,快速掌握Scala编程的基础知识,并能够灵活运用到实际项目中去。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值