一门多范式的编程语言Scala学习收尾-函数的使用
4、集合(接着上次的集合继续学习)
4.4可变集合
1、ListBuffer
val listBuffer1: ListBuffer[Int] = new ListBuffer[Int]
println(s"$listBuffer1")
listBuffer1.+=(11)
listBuffer1.+=(22)
listBuffer1.+=(33)
listBuffer1.+=(11)
listBuffer1.+=(55)
listBuffer1.+=(22)
listBuffer1.+=(33)
listBuffer1.+=(66)
listBuffer1.+=(33)
println(s"$listBuffer1")
/**
* 这里的可变List集合,对于不可变的集合的功能,这里都可以调用
*/
//删除元素,从左向右找元素,只会删除第一次找到的
val res1: listBuffer1.type = listBuffer1.-=(33)
println(s"$res1")
//批量添加元素
val res2: listBuffer1.type = listBuffer1.+=(12, 34, 56)
println(s"$res2")
//添加list集合
val list1: List[Int] = List(1, 2, 3)
val res3: listBuffer1.type = listBuffer1.++=(list1)
println(s"$res3")
2、HashSet
/**
* 可变的set集合,特点和不可变的set一致
*/
val hashset: mutable.HashSet[Int] = new mutable.HashSet[Int]
val hashset1: hashset.type = hashset.+=(1, 2, 3, 4, 5, 3, 7, 6, 8, 3)
println(s"$hashset1")
4.5Tuple
object Demo17tuple {
def main(args: Array[String]): Unit = {
/**
* 大小,值是固定的,根据创建的类来定,每个元素的数据类型可以是不一样,最高可以创建存储22个元素的元组
*/
// val t1: (String, Int) = Tuple2("zhangsan", 18)
// println(s"$t1")
val s1: student1 = new student1("lisi", 20, "nan")
val t2: (String, student1) = Tuple2("hello", s1)
println(t2._2.name)
}
}
case class student1(name:String,age:Int,gender:String)
4.6Map
object Demo18Map {
def main(args: Array[String]): Unit = {
//创建Map集合
//键是唯一的,键一样的时候,值会被覆盖
val map1: Map[Int, String] = Map((1001, "zhangsan"), (1002, "lisi"), (1003, "wangwu"), (1001, "abc"), 1004 -> "bcd")
println(s"$map1")
//根据获取值,直接使用小括号,键不存在会报错,但是使用get方法键不存在不会报错
val res1: String = map1(1003)
val res2: Option[String] = map1.get(1005)
println(s"$res1")
println(s"$res2")
println(map1.getOrElse(1006,0))
val keys: Iterable[Int] = map1.keys // 获取所有的键,组成一个迭代器
for (e <- keys) {
println(e)
}
println("=" * 50)
val values: Iterable[String] = map1.values // 获取所有的值,组成一个迭代器
for (e <- values) {
println(e)
}
//遍历Map集合第一种方式,先获取所有的键,根据键获取每个值
val res5: Iterable[Int] = map1.keys
for(e<-res5){
val value1: Any = map1.getOrElse(e, 0)
println(s"键:${e}, 值:${value1}")
}
//遍历Map集合第二种方式,先获取所有的键,根据键获取每个值
for (kv <- map1) { // 直接遍历map集合,得到每一个键值对组成的元组
println(s"键:${kv._1}, 值:${kv._2}")
}
//遍历Map集合第三种方式,先获取所有的键,根据键获取每个值,采用foreach循环的方式
map1.foreach((kv:(Int,String))=>println(s"键:${kv._1}, 值:${kv._2}"))
}
}
5、Scala中的JDBC
* jdbc的连接步骤
* 1、注册驱动
* 2、创建数据库连接对象
* 3、创建数据库操作对象
* 4、执行sql语句
* 5、如果第四步是查询语句,那么就需要分析查询结果
* 6、释放资源
object Demo19JDBC {
def main(args: Array[String]): Unit = {
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver")
//2、创建数据库连接对象
//jdbc:数据库名://host:port/数据库?xxx=xxx&xxx=xxx
val conn: Connection = DriverManager.getConnection("jdbc:mysql://192.168.214.100:3306/Scala_test?useUnicode=true&characterEncoding=UTF-8&useSSL=false", "root", "123456")
//创建数据库操作对象
val preparedStatement: PreparedStatement = conn.prepareStatement("select * from students where clazz=?")
//执行sql语句,提交任务执行
preparedStatement.setString(1,"理科二班")
val resultSet: ResultSet = preparedStatement.executeQuery()
//分析
while (resultSet.next()){
val id: Int = resultSet.getInt("id")
val name: String = resultSet.getString("name")
val age: Int = resultSet.getInt("age")
val gender: String = resultSet.getString("gender")
val clazz: String = resultSet.getString("clazz")
println(s"学号:$id, 姓名:$name, 年龄:$age, 性别:$gender, 班级:$clazz")
}
//关闭连接
conn.close()
}
}
6、Scala中读取json数据
import com.alibaba.fastjson.{JSON,JSONArray,JSONObject}
import scala.io.Source
object ScalaJson {
def main(args: Array[String]): Unit = {
//读取json文件数据
val lineList: List[String] = Source.fromFile("scala/data/stu.json").getLines().toList
val strJson: String = lineList.mkString("\r\n")
/**
* 使用fastjson包中的JSON类,将一个字符串转换成json格式
* 转换成json对象之后可以通过键获取值
* parseObject将整体转换成一个json数据
*/
val parObject: JSONObject = JSON.parseObject(strJson)
//获取对应键的值
val stuList: String = parObject.getString("student_list")
println(stuList)
/**
* parseArray是将"[{},{}]"变成一个元素是json对象的数组
*/
val arr1: JSONArray = JSON.parseArray(stuList)
var i=0
//while循环遍历数组的元素,再利用键获取值
while (i<arr1.size()){
val Object: JSONObject = arr1.getJSONObject(i)
val name: String = Object.getString("name")
val like: String = Object.getString("like")
println(s"${name}的爱好是${like}")
i+=1
}
}
}
7、Java转换成Scala
Java中的集合原本是无法转换成Scala中的集合的,没有对应的方法
如果要实现转换,我们需要导入隐式转换
导入
import java.util
import scala.collection.JavaConverters._
注意:Scala中的导包可以放在任意位置
import java.util
import scala.collection.JavaConverters._
object Demo21Scala2Java {
def main(args: Array[String]): Unit = {
//创建一个Java的集合
val javaList: util.ArrayList[Int] = new util.ArrayList[Int]()
javaList.add(11)
javaList.add(22)
javaList.add(33)
javaList.add(44)
javaList.add(45)
javaList.add(77)
println(javaList)
val scalaList: List[Int] = javaList.asScala.toList
println(scalaList)
/**
* 对于Scala的集合可以进行转换成Java集合
*/
val list1: util.List[Int] = scalaList.asJava
println(list1)
}
}
8、Scala中的模式匹配
模式匹配可以帮助我们在开发的时候,减少代码量,让逻辑看起来更加清晰,以及可以避免一些异常
语法:
表达式 match {
case 值|[变量名:变量类型]|元组|数组|对象 =>
匹配成功执行的语句
case xxx=>
xxx
_ xxx=>
xxx
}
模式匹配中,如果没有对应的匹配,那么就报错!!!
//匹配变量值
var a: Int = 100
a match {
case 20 => println("20")
case 50 =>println("50")
case _ =>println("true")
// case 100=>println("true")
}
//匹配数据类型
var b:Any=Int
b match {
case Int=>println("true")
case Boolean=>println("false")
}
//匹配元组
val t1: (Int, String, Int) = Tuple3(10001, "zhangsan", 18)
t1 match {
case (a1:Int,a2:String,a3:Int)=>println("true")
}
//匹配数组
val arr1: Array[Any] = Array(1001, "zhangsan", 18, "nan", "oneClazz")
arr1 match {
case Array(id:Int,name:String,gender:Int,age:String,clazz:String)=>
println(s"学号:$id, 姓名:$name, 性别:$gender, 年龄:$age, 班级:$clazz")
}
- 模式匹配的应用
/**
* 模式匹配应用1:避免异常
*/
val map1: Map[Int, String] = Map((1001, "zhangsan"), (1002, "lisi"))
//使用match的方式
val sc: Scanner = new Scanner(System.in)
println("请输入要查询的键:")
val key: Int = sc.nextInt()
map1.get(key) match {
case Some(a:Any)=>println(s"${key}键对应的值为$a")
case None=>println("none")
}
/**
* 模式匹配的应用2:简化代码
*
*/
//不使用match的方法,正常写法
val l1: List[String] = Source.fromFile("scala/data/students.txt").getLines().toList
// l1.map((e:String)=>e.split(","))
// .map((e:Array[String])=>{
// val id: String = e(0)
// val name: String = e(1)
// val age: String = e(2)
// val gender: String = e(3)
// val clazz: String = e(4)
// (id,name,age,gender,clazz)
// }).foreach(println)
//使用模式匹配的方式,简化代码
val arrList: List[Array[String]] = l1.map((e: String) => e.split(","))
/**
* 这里的map使用大括号 {} 而不是小括号 ()
* 是因为大括号可以定义一个代码块(block),而小括号通常用于传递参数给函数
*/
arrList.map {
case Array(id: String, name: String, age: String, gender: String, clazz: String) =>
(id, name,age,gender,clazz)
}
9、Scala中的隐式转换
将一个A类型将来会自动地转换成另一个B类型,类型可以是基本数据类型,也可以是引用数据类型
- 显示转换:
- 直接在变量后面使用to的方式转换,例如toInt
- 或者在函数中传入参数不匹配时,将参数直接to的方式转换类型
9.1 隐式转换函数
//需求:调用fun1函数,就只传字符串,不会报错
//定义隐式转换函数
//在需要返回值类型的功能的时候,自动地根据已有隐式转换函数将参数的类型转成返回值的类型
implicit def implicitFun1(e:String):Int={
return Integer.parseInt(e)
}
//同时定义不止一个隐式转换函数,则效果会不存在
// implicit def implicitFun2(e:String):Int={
// return Integer.parseInt(e)+1000
// }
def fun1(e:Int):Int = e + 1000
val res1: Int = fun1("100")
println(res1)
/**
* 对于字符串方法的使用,如果字符串中存在该方法会自动使用字符串中的方法,
* 而不会使用隐式转换函数的方法
*
*/
println("1000" + 500) // 1000500 // 使用字符串自身的+拼接功能,做字符串拼接
println("1000" - 500) // 500 // 字符串中没有-减法功能,自动使用隐式转换中的函数,将字符串转成数字做减法
println("2000" - 500) // 1500 // 字符串中没有-减法功能,自动使用隐式转换中的函数,将字符串转成数字做减法
/**
* 对于读取文件的隐式转换函数的应用
* 直接自动识别出路径,然后实现getlines的方法
*/
implicit def implicitFun3(path:String): BufferedSource = Source.fromFile(path)
"scala/data/students.txt".getLines().toList.foreach(println)
9.2隐式转换类
object Demo24Implicit2 {
def main(args: Array[String]): Unit = {
/**
* 在定义隐式转换类时,要注意在object中定义:
* `implicit' modifier cannot be used for top-level objects
* implicit class Demo12(path: String) {
* implicit使用的地方,不能超过object作用域
*/
//一般的调用函数的方法
// val demo: Demo1 = new Demo1("scala/data/students.txt")
// demo.show1().foreach(println)
//使用隐式转换函数
val list1: List[String] = "scala/data/students.txt".show1()
list1.foreach(println)
"zhangsan".fun1()
}
implicit class Demo1(path:String){
//定义一个方法
def show1():List[String]={
Source.fromFile(path).getLines().toList
}
def fun1():Any={
println(s"好好学习,天天向上!$path")
}
}
}
9.3隐式转换参数
注意:要定义隐式转换变量,前提就是需要定义一个隐式转换参数
object Demo25Implicit3 {
def main(args: Array[String]): Unit = {
//定义一个隐式转换参数
def fun1(a1: Int)(implicit a2: Int): Int = a1 + a2
//定义一个隐式转换变量
implicit var b1: Int = 100
val i: Int = fun1(100)
println(i)
}
}
10、WordCount实例
package com.scala.jichu
import scala.io.{BufferedSource, Source}
object WordCount {
def main(args: Array[String]): Unit = {
//1、读取数据文件,将每一行的数据封装成集合的元素
val list1: List[String] = Source.fromFile("scala/data/words.txt").getLines().toList
println(list1)
//2、将每一行的数据按照|进行切分,并且进行扁平化操作
val flatlist: List[String] = list1.flatMap((e: String) => e.split("\\|"))
println(flatlist)
//3、根据元素进行分组
val groupList: Map[String, List[String]] = flatlist.groupBy((e: String) => e)
println(groupList)
//4、利用map中kv键值对可以计数的特点,进行计数
groupList.map((kv:(String,List[String]))=>{
val keys: String = kv._1
val counts: Int = kv._2.size
(keys,counts)
}).toList.foreach(println)
println("="*50)
/**
*使用链式调用进行简写
*/
Source.fromFile("scala/data/words.txt").getLines()
.toList
.flatMap((e:String)=>e.split("\\|"))
.groupBy((e:String)=>e)
.map((kv: (String, List[String])) => {
val keys: String = kv._1
val counts: Int = kv._2.size
(keys, counts)
})
.toList
.foreach(println)
/**
* 再进行简化
*/
Source.fromFile("scala/data/words.txt")
.getLines()
.toList
.flatMap(_.split("\\|"))
.groupBy((e:String)=>e)
.map((kv:(String,List[String]))=>(kv._1,kv._2.size))
.toList
.foreach(println)
}
}