Scala 编程 -Scala基础
1.课程目标
- 安装Scala编译和运行环境
- 熟悉Scala基本语法以及函数式编程
- 熟练掌握Scala数据结构使用以及集合方法操作
2.scala简介以及安装
- scala概念:面向对象和面向函数的多范式编程语言,scala也是基于jvm的编程语言,并且scala可以和java的语法兼容。
- 面向对象:scala是纯面向对象的语言。举例:1+2 :1 其实对象 2 对象 +方法操作 1.+(2)。在scala的世界中,每一个值都是一个对象,每一个操作都是方法操作
- 面向函数:函数2个基本核心
- 函数:是输入数据到输出数据的映射关系, 比如 f(x)=>x*x 。x在整个映射关系过程中不可变
- 函数其实也是一个对象,函数可以赋值给变量、可以作为方法的参数、作为方法的返回值
- Scala编程特点
- 优雅:scala是一个非常优雅的编程语言,能够非常轻松的实现一些重要的功能
- 语言表达能力极强:一般是java开发的3-5倍
- Scala是spark以及kafka等大数据框架开发语言,scala能够融入大数据生态圈
- scala是基于jvm的编程语言,scala具有可移植性,能够与java语法很好兼容
- Scala编译环境的安装
- 安装步骤
- 下载scala SDK https://www.scala-lang.org/
- 解压缩并且规划安装目录
- 配置环境变量 定位到bin目录
- object HelloWord{
def main(arr:Array[String]):Unit={ println("helloword") } }
- 基于IDEA 开发scala应用程序
3.scala基础语法
3.1变量
3.2数据类型
3.3 操作符
- 算数运算符: + - * / %
- 逻辑运算符:&& || !
- 比较运算符: > < >= <=
- scala中运算符都是方法操作
3.4 逻辑表达式
3.4.1 if表达式
3.4.2 块表达式
3.4.3 for循环
基本语法:
for(变量 <- 集合数组表达式) {
循环体
}
/**
* for(变量 <- 集合数组表达式) {
* 循环体
* }
* to: 返回的是集合 是一个闭区间集合 0 1 2 3
* until :返回的是一个集合 是一个开区间集合
*/
for (index <- 0 to list.size() - 1) {
println(list.get(index))
}
println("------------------------")
for (index <- 0 until list.size()) {
println(list.get(index))
}
注意: index 是不可变的val类型,在每次循环过程中都会创建新的index变量。
*凡是省略val或者var的地方 默认都是val的
基本语法:
for(变量 <- 集合数组表达式 if 条件语句 * ) {
循环体
}
for (index <- 0 until list.size()
if list.get(index).contains("Hadoop")
if list.get(index).contains("storm")
) {
println(list.get(index))
}
基本语法:
for(变量 <- 集合数组表达式; 变量 <- 集合数组表达式) {
循环体
}
//hadoop 内容列表
val hadoopList = new util.ArrayList[String]()
hadoopList.add("mapreduce")
hadoopList.add("hdfs")
//java 内容列表
val javaList = new util.ArrayList[String]()
javaList.add("JavaSE")
javaList.add("JavaWeb")
javaList.add("javaEE")
val map = new util.HashMap[String,util.List[String]]()
map.put("hadoop",hadoopList)
map.put("java",javaList)
/**
* hadoop
* --mapreduce
* --hdfs
* java
* -JavaSE
* -JavaWeb
* -javaEE
*/
val keyArray = map.keySet().toArray() //scala中array
/**
* for(变量 <- 集合数组表达式; 变量 <- 集合数组表达式) {
* 循环体
* }
*/
for (key <- keyArray if key.equals("java"); list = map.get(key); index <- 0 until list.size()
if index>0
) {
println(list.get(index))
}
基本语法:
val 集合名称=for(变量 <- 集合数组表达式) yield 表达式 //作用于集合中的每个元素的
val goods = new util.ArrayList[Int]()
goods.add(100)
goods.add(50)
goods.add(25)
//val 集合名称=for(变量 <- 集合数组表达式) yield 表达式
val newGoods = for (index <- 0 until goods.size()) yield goods.get(index) * 0.95
for (g <- newGoods) {
println(g)
}
3.5 方法和函数的定义
3.5.1 函数
1.函数是输入数据到输出数据的映射关系 (x:Int)=>{x*x}
2.函数是一个对象 val 变量名称=函数
格式: val 变量名称=(输入数据)=>{输出数据}
// 定义求平方函数
//{} 省略原则: 当函数体只有一行代码的时候可以省略
val square = (x: Int) => x * x
//函数使用
val result: Int = square(10)
println(result)
println(square)
val square2 = (x: Int) => x * x
println(square2)
val area = (height: Int,width: Int) => height * width
println(area)
val cube: Function3[Int,Int,Int] = (x: Int,y: Int,z: Int) => x * y * z
println(cube(1,2,3))
注意:
函数的类型都是FunctionN N代表的就是函数输入参数的个数 N的最大值是22
在scala中凡是 类N 的 ,N的最大值都是22
// 定义求平方函数
//{} 省略原则: 当函数体只有一行代码的时候可以省略
val square: Int => Int = (x: Int) => x * x
//函数使用
val result: Int = square(10)
println(result)
println(square)
val square2 = (x: Int) => x * x
println(square2)
val area: (Int,Int) => Int = (height: Int,width: Int) => height * width
println(area)
val cube: (Int,Int) => Int = (x: Int,3))
3.5.2 方法定义
3.5.3 方法和函数区别
- 区别:
- 函数是一个对象 具有自己的数据类型 和方法 toString hashcode 等方法操作
- 方法:只能够定义在对象或者类的内部,以类的成员存在
- 方法可以升级成函数
4.Scala中数据结构
- Scala中集合
- Array 数组
- List 链表
- Tuple 元组
- Map 映射
- Set 集
- 在scala中 Array List Map Set 又分为了可变集合和不可变集合操作
- 可变集合 存在于scala.collection.mutable 包
- 不可变的集合 存在于scala.collection.immutabl 包
- 这里的不可变 就相当于javaString类型变量,每次操作都会产生新的对象
- 说明:主要通过增 删 改 查 遍历操作学习集合
4.1 Array
4.1.1 不可变的Array (长度不可变)
第一种:
val 名称=new Array[数据类型](数组的长度)
第二种:
val 名称=Array[数据类型](初始化数据)
//val 名称=new Array[数据类型](数组的长度)
//创建一个Int类型的长度为3数组
val arr = new Array[Int](3)
//val 名称=Array[数据类型](初始化数据)
//创建一个String类型的数组
val strArray = Array[String]("hadoop","scala","spark")
//赋值和修改
strArray(0) = "kafka"
for (str <- strArray) println(str)
4.1.2 可变数组 ArrayBuffer (长度和数据都是可以改变)
声明格式:
val 名称=new ArrayBuffer[数据类型](长度)
val 名称=ArrayBuffer(初始化数据)
object Scala_day01_arrayBuffer {
def main(args: Array[String]): Unit = {
//val 名称=ArrayBuffer(初始化数据)
val strArrayBuffer = ArrayBuffer[String]("hadoop","spark")
/**
* 增加
* += 可以增加一个 或者多个元素
* 删除
* -= 删除一个或者多个元素
*/
strArrayBuffer += "java"
strArrayBuffer += ("hbase","hive","impala")
strArrayBuffer-=("hbase","impala")
strArrayBuffer(0)="mapreduce"
//遍历
for (str <- strArrayBuffer) println(str)
}
}
注意:arr(index) 实际上都是方法操作
- 数组:
- 有序 随机遍历效率非常高,删除和随机插入操作效率非常低
- 数组在多线程环境下都是不安全,数组的值可以进行改变
4.2 List
- List是一个链表结构 head(当前存储的元组)和tail(除了当前元素的 所有元素 tail 也是一个list)
4.2.1 不可变list(长度和数据都是不可变)
格式: val 名称=List[数据类型](初始化数据)
val 名称 = "初始化数据"::"初始化数据":: Nil
// val 名称=List[数据类型](初始化数据)
val strList = List[String]("hadoop","spark")
/**
* 增加操作
* 头部: ::,+: 向列表头部增加一个数据
* ::: ++: 增加另外一个列表
* 尾部: :+ 向列表头部增加一个数据
* ++ 增加另外一个列表
*/
val javaWebList = "javaWeb" :: strList
val htmlList = "HTML" +: javaWebList
val javaSeList = List("JavaSE","Mysql","mybaties") ::: htmlList
val elkList = javaSeList :+ "ELK"
val flinkList=elkList++List("Flink","kylin","druid")
/**
* 删除
* drop 方法
*/
val dropList=flinkList.drop(6) //从列表的头部开始进行删除 或者列表左边
val dropRightList=dropList.dropRight(3)
/**
* 修改操作
*/
val updateList=dropRightList.updated(0,"java")
//遍历
for (str <- updateList) println(str)
注意: 在scala中 凡是以:结尾的方法操作 在使用过程中,都会作用于方法的右侧
4.2.2 可变列表操作 ListBuffer (长度可变)
声明格式:
val 名称=new ListBuffer[数据类型](初始化长度)
val 名称=ListBuffer[数据类型](初始化数据)
//val 名称=ListBuffer[数据类型](初始化数据)
val strListBuffer = ListBuffer[String]("hadoop","spark","scala")
/**
* 增加操作
* += 添加一个或者多个
* ++= 添加另外一个列表
* 删除操作
* -= 删除一个或者多个
* --= 删除另外一个列表
*/
strListBuffer += "hive"
strListBuffer ++= List("impala","hbase","kafka")
strListBuffer-="scala"
strListBuffer--=List("hbase","kafka")
val updateList=strListBuffer.updated(0,"flink")
println(strListBuffer(0))
println("--------------------")
for (str <- updateList) println(str)
- 定义个方法,该方法具有多个不同数据类型的返回值(List,Array)
4.3 Tuple 元组(不可变)
元组:使用小括号括起来的不同数据类型的一个集合
val 名称=(不同数据类型的初始化数据)
注意: tuple 都是继承 TupleN的操作 N 是集合中数据的个数 N<=22
//val 名称=(不同数据类型的初始化数据)
object Scala_day01_tuple {
def getListAndArray(): Tuple2[List[String],Array[Int]]={
val list = List ("hadoop","spark")
val array = Array (20,10,30)
(list,array) //Tuple2
}
def main(args: Array[String]): Unit = {
//val 名称=(不同数据类型的初始化数据)
val tuple: Tuple4[String,Double,Boolean] = ("hadoop",12.5,true)
//访问数据
println(tuple._1)
println(tuple._2)
println(tuple._3)
println(tuple._4)
println(tuple.getClass)
println("-----------------------")
val t= getListAndArray()
println(t._1)
println(t._2.toBuffer)
println("-----------------------")
val (strlist,intArray)=getListAndArray()
println(strlist)
println(intArray.toBuffer)
}
}
val tuple2Array=Array(
("hadoop",10),("scala",20),("spark",30)
) //这种结构类似于map 在scala中map中元素是不是基于tuple2构成的呢? 是的
4.4 Map 映射
4.4.1不可变的map操作
val 名称=Map[key数据类型,value数据类型](key -> value,key -> value,key -> value)
val 名称=Map[key数据类型,value数据类型]((key,value),(key,value),(key,value))
object scala_day01_map {
def main(args: Array[String]): Unit = {
//val 名称=Map[key数据类型,value数据类型](key -> value,key -> value,key -> value)
val map = Map[String,Int]("hadoop" -> 10,"scala" -> 5,"spark" -> 20)
//访问map中的元素
println(map("hadoop"))
//println(map("java"))
println(map.get("hadoop").get) //get方法的返回值 是Option 表示可选向 有值 返回Some(value) 没值 None
println(map.getOrElse("java",100)) //推荐使用这种方法
//+ 增加 和修改
val newMap = map + ("hadoop" -> 100,"fink" -> 30)
//删除
val scalaMap = newMap - ("scala","fink")
println(scalaMap)
for (t <- map) {
println(t._1 + "t" + t._2)
}
println("---------------------")
for ((k,v) <- map) {
println(k + "t" + v)
}
}
}
4.4.2 可变的Map
导包: import scala.collection.mutable
val 名称=mutable.Map[key数据类型,value数据类型]()
object scala_day01_mutablemap {
def main(args: Array[String]): Unit = {
//val 名称=new mutable.Map[key数据类型,value数据类型]()
val map = mutable.Map[String,Int]()
/**
* 增加数据
* += 增加一个或者多个元素 或者修改一个或者多个元素
* ++= 增加另外一个map
* 删除数据
* -= 删除一个或者多个数据
* 修改
*/
map += ("hadoop" -> 10,"spark" -> 20)
map ++= Map("scala" -> 100) //不可变的Map
map-=("scala","spark")
map += ("hadoop" -> 100,"spark" -> 20)
for ((k,v) <- map) println(k + "t" + v)
}
}
4.5 Set集合
4.5.1 不可变Set集合
val 名称 =Set[String](初始化数据)
//val 名称 =Set[数据类型](初始化数据)
val set = Set[Int](6,5,1,3,4,4)
val newSet = set + 10
val newSet2 = newSet + (12,11)
val removeSet = newSet2 - (1,2)
//遍历
for (s <- removeSet) println(s)
println("----------------------------")
val set2 = Set[Int](2,6,8,10)
//求并集操作 set set2
val set3 = set ++ set2
println(set3)
//求交集 set set2 (2,6)
val set4=set & set2
println(set4)
//求差集 set 与set2 (1,3)
val set5 =set &~ set2
println(set5)
4.5.2 可变Set
5.符号操作
- 不可变的集合: + - ++ :: +: ::: ++: 等
- 可变集合:+= ++= -= --=
6.集合中常用方法操作
6.1 单个集合的操作
val arr = Array[Int](1,9,4)
//求sum值
println(arr.sum)
//求最大值最小值
println(arr.max)
println(arr.min)
//排序 默认升序
println(arr.sorted.toBuffer)
//reverse 将集合元素进行翻转
println(arr.sorted.reverse.toBuffer)
//去重操作
println(arr.distinct.toBuffer)
//通过数组元素构建字符串
println(arr.mkString("-"))
6.2 两个集合的操作方法
val intArray = Array[Int](1,7,20,30)
val strArray = Array[String]("hadoop","java","hive")
//zip 拉链操作
val zipArray = strArray.zip(intArray)
println(zipArray.toBuffer)
//zipAll
/**
* 第一个参数:集合
* 第二个参数:第一个集合中默认数据
* 第三个参数:第二个集合中默认数据
*/
val zipAllArray = strArray.zipAll(intArray,"itcast",100)
println(zipAllArray.toBuffer)
//创建二维数组 扁平化操作
val arrArray = Array(
Array[Int](1,3),Array[Int](4,6),Array[Int](7,9)
)
println(arrArray.flatten.toBuffer)
6.3 集合中高阶操作
- 高阶操作:就是将函数作为方法的参数
package cn.itcast.day01
object scala_day01_api3 {
def main(args: Array[String]): Unit = {
val arr = Array[Int](1,9)
//foreach 操作
val f: Int => Unit = (x: Int) => println(x)
arr.foreach(f)
println("-------------------------")
//使用匿名函数
arr.foreach((x: Int) => println(x))
println("-------------------------")
//使用匿名函数 输入数据的数据类型可以省略的
arr.foreach(x => println(x))
//将一个集合通过函数作用在集合中的每一个元素 并且构建新的集合
val mapArray = arr.map(x => {
x * x
})
println(mapArray.toBuffer)
//过滤操作 filter 偶数
val filterArray = arr.filter(x => x % 2 == 0)
println(filterArray.toBuffer)
//count 统计数据个数
val count = arr.count(x => x % 2 == 0)
println(count)
val strArray = Array[String](
"hadoop,scala,spark,html","java,javaEE,html,hadoop,java"
)
//将数组中的每个元素 按照一定规则进行切分,汇总成一个集合
val flatMapArray: Array[String] = strArray.flatMap(x => x.split(","))
println(flatMapArray.toBuffer)
val groupMap: Map[String,Array[String]] = flatMapArray.groupBy(x => x)
println("--------------------------")
groupMap.foreach((t: Tuple2[String,Array[String]]) => {
println(t._1 + "t" + t._2.toBuffer)
})
println("----------------------")
val map = Map[String,Array[Tuple2[String,Int]]](
"hadoop" -> Array(
("hadoop",("hadoop",30)
),"spark" -> Array(
("spark","java" -> Array(
("java",100),("java",150),180)
)
)
//需求: 求每一个key值下边 对应值的总和
//hadoop -> 60 spark->40 java ->430
val resultMap: Map[String,Int] = map.mapValues((arr: Array[Tuple2[String,Int]]) => {
val valueArray: Array[Int] = arr.map(t => t._2)
valueArray.sum
})
println(resultMap)
println("--------------------------------")
val arr2 = Array[Int](1,9)
val sum=arr2.reduce(
//x 临时变量 初始值 0 每次操作都会进行累加
//y arr2中每一个元素
(x,y)=>x+y
)
println(sum)
}
}
7.案例 基于scala求wordcount
- 需求:读取三个文件 a.txt b.txt c.txt 统计这三个文件中每个单词出现的次数
- 操作步骤:
- 读取文件 Source.from
- 对每一个文件进行统计操作
- 将每一个文件的统计结果汇总 ListBuffer
- 根据汇总结果 再次进行统计
-
package cn.itcast.day01
import java.io.File
import scala.collection.mutable.ListBuffer
import scala.io.Source
object scala_day01_wordocunt {
/**
* 统计文件中每一个单词出现的个数
*
* @param path
* @return
*/
def getFileData(path: String): Map[String,Int] = {
val array = Source.fromFile(new File(path)).getLines().toArray
val wordArray: Array[String] = array.flatMap((x: String) => x.split(","))
val wordPair: Array[Tuple2[String,Int]] = wordArray.map((word: String) => (word,1))
val wordPairArray: Map[String,Int]]] = wordPair.groupBy((t: Tuple2[String,Int]) => t._1)
val mapResult: Map[String,Int] = wordPairArray.mapValues((f: Array[Tuple2[String,Int]]) => f.length)
mapResult
}
def main(args: Array[String]): Unit = {
val array = Array[String]("d:/a.txt","d:/b.txt","d:/c.txt")
val listBuffer = new ListBuffer[Map[String,Int]]()
//统计三个文件中数据 并且汇总到集合中
for (path <- array) {
val fileData: Map[String,Int] = getFileData(path)
listBuffer += fileData
}
val flattenList: ListBuffer[Tuple2[String,Int]] = listBuffer.flatten
val wordPairListBuffer: Map[String,ListBuffer[Tuple2[String,Int]]] = flattenList.groupBy(t => t._1)
val resultData: Map[String,Int] = wordPairListBuffer.mapValues((tuple2ListBuffer: ListBuffer[Tuple2[String,Int]]) => {
val mapListBuffer: ListBuffer[Int] = tuple2ListBuffer.map(t => t._2)
mapListBuffer.sum
})
println(resultData)
}
}
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|