Scala
Scala是把函数式编程思想和面向对象编程思想结合的一种编程语言
- 在面向对象编程中,我们把对象传来传去。那在函数式编程中,我们要做的是把函数传来传去,而这个,说成术语,我们把他叫做高阶函数。
- 在函数式编程中,函数是基本单位,他几乎被用作一切,包括最简单的计算,甚至连变量都被计算所取代。在函数式编程中,变量只是一个名称,而不是一个存储单元,这是函数式编程与传统的命令式编程最典型的不同之处。
java与Scala互相兼容
- java 与 scala 可以相互兼容,是类可以兼容
package com.shujia.scala;
public class Demo1Java {
/**
* java中方法不加static是一个配普通方法,普通方法需要通过类的对象才能调用
*
* main函数是由虚拟机调用的,加上static才能通过类名直接调用(实际上是由“类对象”调用的)
* 类对象:class文件被加载到内存中的一个对象
*
* (.java)编译(.class) -- 运行 -- JVM
*/
public static void main(String[] args) {
System.out.println("java");
//在java中使用scala的类
Demo4Student demo4Student = new Demo4Student();
String s = demo4Student.print("java");
System.out.println(s);//java:scala
}
}
package com.shujia.scala
/**
* main函数必须放在object中才能运行
*
* object:修饰的类直接就是一个对象,单例
*
*/
object Demo2Scala {
/**
* def: 定义方法的关键字
* main: 函数名
* args: Array[String] : 函数的参数
* args : 参数名
* Array[String] : 参数类型 ,[String] 泛型
* Unit: 相当于void
* {} 中是函数体
*/
def main(args: Array[String]): Unit = {
println("scala")
//在scala中使用java的类
var student = new Demo3Student("001", "张三", 23)//
println(student.getName)//张三
println(student)
/** 类型推断: 变量的类型会自动通过等号右边推断出来
* 也可以加上类型
*/
val age: Int = student.getAge
/**
* var :定义一个变量,变量可以重新指向其他的对象
* val :定义不可变的变量,不能在指向其它的对象
* 一般使用val
*/
/**
* String: scala中的String就是java中的String
*
*/
val s: String = "scala"
val split = s.split(",")
/**
* println函数底层和java是一样的
* scala方式
*/
println(split)
//也可以使用java的方式
System.out.println(split)
}
}
package com.shujia.scala;
public class Demo3Student {
private String id;
private String name;
private int age;
@Override
public String toString() {
return "Demo3Student{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
//构造方法
public Demo3Student() {
}
public Demo3Student(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
//成员方法
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.shujia.scala
class Demo4Student {
def print(str: String): String = {
return str + ":scala"
}
}
语法基础
package com.shujia.scala
import java.io.{BufferedReader, FileReader}
import java.sql.DriverManager
import scala.io.{BufferedSource, Source}
object Demo5base {
def main(args: Array[String]): Unit = {
/**
* 1、变量
*
* val: 常量,不能再指向其它的对象,相当于java中给变量增加final修饰
* var :变量,可以再指向其它的对象
*
* 一般尽量使用val
*/
val i: Int = 100
println(i)
val j = i + 1
println(j)//101
//不能指向其它对象: i = 200
var a = 200
a = 300
println(a)
//2、自动推断类型
val str1 = "java"
//手动加上类型
val str2: String = "java"
//多态,父类的引用指向子类的对象。就只有父类的方法了
val str3: Object = "java"
/**
* 3、类型转换
*
* 在scala中只要你确定类型转换没有问题,都可以直接to
*/
val s: String = "100"
//java中类型转换
val si: Int = Integer.parseInt(s)
//scala中的类型转换。toInt底层还是java的Integer.parseInt
val sj: Int = s.toInt //隐式转换: 可以给对象动态增加方法
println(sj)//100
/**
* 4、文件读写
* java方式:
*/
val fileReader = new FileReader("scala/data/students.txt")
val bufferedReader = new BufferedReader(fileReader)
//读取第一行
var line: String = bufferedReader.readLine()
//判断是否为空
while (line != null) {
println(line)
//读取下一行
line = bufferedReader.readLine()
}
bufferedReader.close()
println("================================")
/**
* scala中读取文件
*
*/
val source: BufferedSource = Source.fromFile("scala/data/students.txt")
/** *
* 迭代器的数据可能并没有完全加载到内存中
*
* 迭代器只能迭代一次
*
*/
//读取所有行,返回一个迭代器
val lines: Iterator[String] = source.getLines()
//循环遍历迭代器。可看到全部数据
for (line <- lines) {
println(line)
}
println("===============================")
//链式调用
val liness = Source
.fromFile("scala/data/students.txt")
.getLines()
/**
*
* 5、JDBC:使用方式和java中没有区别
*
*/
//1、加载驱动
Class.forName("com.mysql.jdbc.Driver")
//2、创建链接
val con = DriverManager.getConnection("jdbc:mysql://master:3306/student", "root", "123456")
//查询数据
println(con)
/**
* 6、字符串拼接
*
*/
val k = 100
//底层就是stringBuilder
val ss = s"java,asdasda,${k}" // scala的拼接方式,s是一个方法
println(ss)//java,asdasda,100
//java的方式
val stringBuilder = new StringBuilder
stringBuilder.append("java")
stringBuilder.append(k)//java100
println(stringBuilder.toString())//java100
}
}
类和对象
package com.shujia.scala
object Demo6Class {
def main(args: Array[String]): Unit = {
val stu = new Student("001", "张三", 23)
println(stu._age) //23
println(stu._name) //张三
println(stu) //Student(001,张三,23,null)
val stu2 = new Student("002", "李四", 24, "男")
println(stu2) //Student(001,张三,23,男)
/**
* 类中的普通方法需要通过类的对象才能调用
* object中的方法可以直接调用
*/
val i = TextObject.fun("100")
println(i)
}
}
/**
* 在类中可以定义属性,方法,构造函数
*
*/
class Student(id: String, name: String, age: Int) {
println("默认构造函数")
//定义属性并赋值
val _id: String = id
val _name: String = name
val _age: Int = age
//下划线是一个占位符,起到占用位置的作用
var _gender: String = _ //后面要对_gender进行赋值,所以用var
/**
* 重载构造函数 this
* 在重载构造函数的第一行需要显示调用默认构造函数
*/
def this(id: String, name: String, age: Int, gender: String) {
//println("重载构造函数") 重载构造函数不在第一行会报错
this(id, name, age)
println("重载构造函数")
//赋值
this._gender = gender
}
/**
* override:重写父类的方法
*
*/
override def toString: String = {
//默认函数最后一行作为返回值,所以return可以省略
s"Student(${_id}, ${_name}, ${_age},${_gender})"
}
}
/**
* 定义一个单例模式的对象
* 对象中的方法可以直接调用
*
*/
object TextObject {
def fun(s: String): Int = {
s.toInt
}
}
继承
package com.shujia.scala
object Demo7Extends {
def main(args: Array[String]): Unit = {
val b = new B("001", "李四", "男") //先调用父类的函数
println(b) //A(001,李四,男) 子类B中重写了,拼接写的是A
}
}
class A(id: String, name: String) {
println("A的默认构造函数")
val _id: String = id
val _name: String = name
override def toString = s"A(${_id}, ${_name})"
}
/**
* 继承类同时调用构造函数
*/
class B(id: String, name: String, gender: String) extends A(id, name) {
println("B的默认构造函数")
val _gender: String = gender
//重写父类的方法
override def toString = s"A(${_id}, ${_name},${_gender})"
}
样例类
package com.shujia.scala
object Demo8CaseClass {
def main(args: Array[String]): Unit = {
//样例类可以不适用new创建对象
val p = Person("id", "李四", 23)
println(p.age)
println(p.id)
println(p.name)
println(p)
//如果需要修改属性的值,需要将修饰符改成var,默认是val
p.age = 200
}
}
/**
*
* 样例类:scala在编译的时候会自动给样例类增加方法(toString,hashCode)
* 可以定义在任何地方,里面/外面都可以
*/
case class Person(id: String, name: String, var age: Int)
Apply(伴生对象)
package com.shujia.scala
object Demo9Apply {
def main(args: Array[String]): Unit = {
/**
* 不使用new创建对象,实际上是调用伴生对象的apply函数
*/
val dog: Dog = Dog("小狗", 2)
}
}
class Dog(name: String, age: Int) {
}
//伴生对象:定义一个和这个类一样的object
object Dog {
def fun(): Unit = {
println("dog")
}
/**
* applyh函数可以直接通过 "对象名()" 调用
*/
def apply(name: String, age: Int): Dog = {
val dog = new Dog(name, age) //方法里面 new 这个类的对象
return dog
}
}
函数
- 基本格式
package com.shujia.scala
object Demo10Fun1 {
def main(args: Array[String]): Unit = {
/**
* 函数的定义,scala中的函数可以在任何位置定义
*
* def: 定义函数关键字
* fun: 函数的名称
* str: String;函数的参数和参数的类型
* Unit:函数的返回值,Unit代表没有返回值
*/
def fun(str: String): Unit = {
println(str)
}
//调用函数
fun("scala")
/**
* 函数的省略
* 1、return 可以省略,默认最后一行作为返回值
* 2、如果代码只有一行,大括号可以省略
* 3、返回值类型可以省略,scala会自动推断返回值的类型 -->def sToInt(s:String)=s.toInt
* 4、如果函数没有参数,小括号可以省略
*/
def sToInt(s: String): Int = {
return s.toInt
}
//省略:
def sToInt1(s: String) = s.toInt
//调用:
println(sToInt1("100"))
}
}
- 以函数作为参数
package com.shujia.scala
object Demo11Fun2 {
def main(args: Array[String]): Unit = {
/**
* 面向对象编程:将对象传来传去,对象是有类型的,方法的参数是有类型限制的
*
* 面向函数编程:将函数传来传去,函数也是有类型的,接受函数的方法同样有类型限制
*
*
* 高阶函数
* 1、以函数作为参数
* 2、以函数作为返回值
*/
/**
* 函数的类型是由函数 参数的类型 和 返回值的类型 决定
*
* def fun1(str: String): Int = {
* str.toInt
* }
* 这是一个参数为String 返回值为Int类型的函数
*/
/**
* 以函数作为参数--> 定义一个方法,方法的参数是一个函数
*
* fun1 的参数是一个函数,是一个参数为String 返回值为Int类型的函数
*
* String => Int ----> 描述函数的类型
*
*/
def fun1(f: String => Int): Unit = {
// f 相当于fun2的引用
//调用传进来的函数
val i: Int = f("100")
println(i)
}
//这是一个参数为String 返回值为Int类型的函数
def fun2(str: String): Int = {
str.toInt + 1
}
def fun3(str: String) = str.toInt + 2
//调用fun1,传入fun2
fun1(fun2)
fun1(fun3)
//使用lambda表达式调用函数
fun1((s: String) => s.toInt + 100)
//lambda表达式的参数类型可以自动推断出来
fun1(s => s.toInt + 1000)
//如果lambda表达式的参数只使用了一次可以通过下划线代替
fun1(_.toInt + 10000)
/**
* lambda表达式--- 对函数定义的简写--匿名函数
*
* (s: String) => s.toInt
*
* => 前面是函数的参数名和参数的类型,
* => 后面是函数体和返回值
*/
def fun4(str: String): Int = {
str.toInt + 1
}
val lam: String => Int = (str: String) => str.toInt + 1
println(lam("200"))
}
}
- 以函数作为参数的应用
package com.shujia.scala
object Demo12Fun3 {
def main(args: Array[String]): Unit = {
//将数组中的每一个元素加一
// java思维:
val arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
var index = 0
while (index < arr.length) {
val i = arr(index) //java是用[]
val j = i + 1
arr(index) = j
index += 1
}
//mkString 将集合中的元素通过一个分隔符拼接成一个字符串,和split功能相反
println(arr.mkString(",")) //2, 3, 4, 5, 6, 7, 8, 9, 10
/** scala方式:
* map函数: 将集合中的元素一个一个传递给后面的函数,最终返回一个新的集合
*
*/
val arr2: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
val arr3: Array[Int] = arr2.map((i: Int) => i * 2)
println(arr3.mkString(","))
//将集合中的元素奇数加一偶数乘二
val arr4: Array[Int] = arr2.map((i: Int) => {
if (i % 2 == 0) {
//代码块结尾作为返回值
i * 2
} else {
//代码块结尾作为返回值
i + 1
}
})
println(arr4.mkString(","))
//将集合中元素的类型转换成String类型
val strs: Array[String] = arr2.map((i: Int) => i.toString)
//简写
val strs1: Array[String] = arr2.map(i => i.toString)
//简写
val strs2: Array[String] = arr2.map(_.toString)
}
}
- 以函数作为返回值
package com.shujia.scala
object DEmo13Fun4 {
def main(args: Array[String]): Unit = {
def fun1(str: String): String => Int = {
def f(s: String): Int = {
s.toInt + str.toInt
}
//将函数返回
f
}
//调用函数返回一个函数
val fun2: String => Int = fun1("100")
//再调用返回的函数
val i: Int = fun2("20")
println(i)//120
//简化调用的方式
val j = fun1("1")("2")
println(j)//3
/**
* 简化函数的定义
*
*/
def fun3(str: String)(s: String): Int = {
s.toInt + str.toInt
}
val k = fun3("100")("1000")
println(k)//1100
}
}
集合
- List
package com.shujia.scala
object Demo14List {
def main(args: Array[String]): Unit = {
/**
* list 集合
*
* 有序不唯一
*
* 在scala这种默认使用的集合是不可变的集合
*
*/
val list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 1)
//通过下标获取数据
println(list(1))
//将集合中的元素通过分隔符拼接成一个字符串。集合数组都有这些函数功能
println(list.mkString("-"))//1-2-3-4-5-6-7-8-9-1
//最大值
println(list.max)
//最小值
println(list.min)
//求和
println(list.sum)
//获取长度
println(list.size)
//获取第一个元素
println(list.head)
//获取最后一个元素
println(list.last)
//获取前几个元素,会返回一个新的集合。 因为原集合不可变
println(list.take(2))//List(1,2)
//取出不包含第一个元素的所有元素
println(list.tail) //List(2, 3, 4, 5, 6, 7, 8, 9, 1)
//反转集合,返回一个新的集合
println(list.reverse)
//判断是否为空
println(list.isEmpty)
//去重
println(list.distinct) //List(1, 2, 3, 4, 5, 6, 7, 8, 9)
/**
* map函数,对集合中的元素进行处理,将集合中的元素一个一个传递给后面的函数
* 处理完了之后返回一个新的集合
*
* 数据的对应关系是一对一
*/
val l: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 1)
val l2: List[Double] = l.map((i: Int) => i.toDouble + 100)
println(l2)
/**
* filter函数:对集合中的元素进行过滤
* 将集合中的元素传递给后面的函数,如果函数最终返回true保留元素,如果函数返回false过滤元素
*
* 返回一个新的集合,新的集合类型和源集合一致
*/
//取出集合中所有的奇数
val l3: List[Int] = l.filter((i: Int) => i % 2 == 1)
println(l3)//(1,3,5,7,9,1)
/**
* sortBy:指定一个排序的列对数据进行排序,默认是升序
* 传入一个排序的列
*/
val l4: List[Int] = l.sortBy((i: Int) => i) //只有一列,那就是i。 -i是倒序
println(l4) //List(1, 1, 2, 3, 4, 5, 6, 7, 8, 9)
/**
* sortWith: 传入一个比较规则
*
*/
val l5 = l.sortWith((x: Int, y: Int) => x < y) //传入前一个数,后一个数。按照升序排序
println(l5) //List(1, 1, 2, 3, 4, 5, 6, 7, 8, 9)
/**
* flatMap函数,将集合中的元素压扁,一行变多行
*
* 数据的对应关系是一对多
*
* map 函数需要的参数也是一个函数,函数的返回值必须是一个集合或者数组,
* map函数会将返回的集合压扁
*
*/
val lines: List[String] = List("java,spark,hadoop", "spark,java,hive", "hive,hbase")
val words= lines.flatMap((line: String) => line.split(","))
println(words)//List(java,spark,hadoop,spark,java,hive,hive,hbase)
}
}
- ListBuffer
package com.shujia.scala
import scala.collection.mutable.ListBuffer
object Demo15ListBuffer {
def main(args: Array[String]): Unit = {
/**
* 可变集合
*
*/
val listBuffer: ListBuffer[Int] = new ListBuffer[Int]
//增加元素
listBuffer.+=(1)// +=是一个方法
//简写省略
listBuffer += 2
println(listBuffer) //ListBuffer(1, 2)
//增加多个元素
listBuffer ++= List(1, 2, 3, 5)
println(listBuffer) //ListBuffer(1, 2, 1, 2, 3, 5)
//删除一个元素
listBuffer -= 2
println(listBuffer) //ListBuffer(1, 1, 2, 3, 5)
//通过下标获取元素
println(listBuffer(2)) //2
//通过下标更新元素
listBuffer.update(4, 10)
println(listBuffer)
//通过下标更新元素
listBuffer(4) = 100
println(listBuffer)
//将listbuffer转换成list。转后成List就不可变了
val list: List[Int] = listBuffer.toList
println(list) //List(...)
}
}
- set
package com.shujia.scala
import scala.collection.mutable
import scala.collection.mutable.HashSet
object Demo16Set {
def main(args: Array[String]): Unit = {
/**
* set 无序唯一
* 不可变
*/
val set: Set[Int] = Set(12, 3, 123, 124, 123, 124, 12, 321, 4, 123, 123124, 32)
println(set) //Set(321, 124, 123124, 32, 12, 3, 123, 4)
println(set.max)
println(set.min)
println(set.sum)
println(set.mkString(","))
println(set.map(i => i * 2))
println(set.filter(i => i % 2 == 1))
val s1 = Set(1, 2, 3, 4, 5, 6, 7)
val s2 = Set(3, 4, 5, 6, 7, 8, 9)
println(s1 & s2) //交集 Set(5, 6, 7, 3, 4)
println(s1 | s2) //并集
println(s1 &~ s2) //差集 Set(1, 2)
/**
* 可变Set
*
*/
val hashSet = new mutable.HashSet[String]()
hashSet.add("java")
hashSet += "spark"
println(hashSet)// Set(java,spark)
//清空
hashSet.clear()
println(hashSet)//Set()
}
}
- map
package com.shujia.scala
import scala.collection.mutable
import scala.collection.mutable.HashMap
object Demo17Map {
def main(args: Array[String]): Unit = {
/**
* map: kv格式
* 不可变
*/
val map = Map(("001", "张三"), ("002", "李四"), "003" -> "王五")
println(map) //Map(001 -> 张三, 002 -> 李四, 003 -> 王五)
//通过key获取alue
println(map("001")) //如果key不存在直接报错
println(map.get("001")) //如果key不存在返回None
println(map.getOrElse("004", "默认值")) //如果key不存在返回默认值
//判断key是否存在
println(map.contains("001"))
val map2: Map[String, String] = map.filter((kv: (String, String)) => kv._2.equals("张三"))
println(map2) //Map(001 -> 张三)
println(map.keys) //取出所有的key
println(map.values) //去除所有的value
/**
* 可变map
*
*/
val hashMap = new mutable.HashMap[String, Int]()
//增加元素
hashMap.+=(("001", 23))
//简写
hashMap += "002" -> 24
println(hashMap)
//删除元素
hashMap -= "001"
println(hashMap)
hashMap.remove("002")
println(hashMap)
}
}
- 元组
package com.shujia.scala
object Demo18Tuple {
def main(args: Array[String]): Unit = {
/**
* 元组:结构简单,可以通过下标取数据,不会出现下表越界。没有其他方法
*
* 元组中最多可以有22个元素
*/
val t = (1, 2, 3, 4, 5, 6)
println(t._1)//1
println(t._6)//6
val t2 = ((1, 2), (2, 3, (5, 6)))
println(t2._1._2)
println(t2._2._3._1)
}
}
WordCount
- JavaWordCount
package com.shujia.scala;
import scala.Int;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.HashMap;
public class Demo19JavaWordCount {
public static void main(String[] args) throws Exception {
//使用hashmapb凹槽最终的结果
HashMap<String, Integer> countMap = new HashMap<>();
//1、读取文件
BufferedReader reader = new BufferedReader(new FileReader("scala/data/words.txt"));
String line;
while ((line = reader.readLine()) != null) {
String[] words = line.split(",");
for (String word : words) {
//如果在hashmap存在这个 单词直接加一,如果不存在,存一个一进去
if (countMap.containsKey(word)) {
Integer integer = countMap.get(word);
countMap.put(word, integer + 1);
} else {
countMap.put(word, 1);
}
}
}
System.out.println(countMap);
}
}
- ScalaWordCount
package com.shujia.scala
import scala.io.Source
object Demo20ScalaWordCount {
def main(args: Array[String]): Unit = {
//1、读取文件
val lines: List[String] = Source.fromFile("scala/data/words.txt").getLines().toList
//2、将每一行中的多个单词拆分出来
val words: List[String] = lines.flatMap(line => line.split(","))
//3、对单词进行分组,将同一个单词分到同一个组中
val groups: Map[String, List[String]] = words.groupBy(word => word)
//4、统计单词的数量
val count: Map[String, Int] = groups.map(kv => {
//一个单词
val word: String = kv._1
//当前单词构建的集合
val ws: List[String] = kv._2
//统计单词的数量
val count: Int = ws.size
//返回单词和单词的数量
(word, count)
})
/**
* foreach: 遍历集合,将集合中的元素一个一个传递给后面的函数,没有返回值
*
*/
count.foreach(kv => println(kv))
/**
* 简写
*
*/
//链式调用
Source
.fromFile("scala/data/words.txt") //读取文件
.getLines() //获取所有行
.toList //转换成list
.flatMap(_.split(",")) //将单词拆分出来
.groupBy(word => word) //按照单词进行分组
.map(kv => (kv._1, kv._2.size)) //统计单词的数量
.foreach(kv => println(kv)) //打印结果
}
}
模式匹配
package com.shujia.scala
object Demo21match {
def main(args: Array[String]): Unit = {
/**
* 模式匹配:
*
* java中的模式匹配可以匹配:基本数据类型,字符串,枚举
*
* scala中的模式匹配可以匹配,基本数据类型字符串,枚举,对象,类型
*/
//匹配基本数据类型
val i: Double = 100.1
i match { // 按照顺序执行case ,只有一个可以匹配成功
case 100 => {
//如果一行不够,增加大括号写多行
println(100)
}
case 10 => println(10)
case 100.1 => println(100.1)
case _ => println("默认")
}
// 匹配字符串
val str: String = "java"
str match {
case "java" => println("java")
case "scala" => println("scala")
}
//匹配对象
case class User(id: String, name: String)
val user: User = User("001", "张三")
user match {
case User("001", "张三") => println("张三")
case User("002", "李四") => println("李四")
case _ => println("其它")
}
/**
* 匹配类型
*
*/
//Any 相当于Object。 是所有类型的超类
val a: Any = "java"
a match {
//如果匹配成功i相当于a的引用
case i: Int => println(s"$i 是int类型")
case s: String => println(s"$a 是一个字符串")
case u: User => println(s"$u 是一个User")
case _ => println("其它")
}
//Option:是一个可选的值,有两个取值,Some None
val map = Map("001" -> "张三", "002" -> "李四")
val opt: Option[String] = map.get("003")
//match 可以有返回值
val value: String = opt match {
case Some(v) => v
case None => "默认值"
}
println(value)
//相当于
println(map.getOrElse("001", "默认值"))
}
}
- 统计班级的人数
package com.shujia.scala
//打印出结果看看 println(lines)
//lines.for看看
//lines.foreach(println) 每一步都遍历一下看看
import scala.io.Source
object Demo22Student {
def main(args: Array[String]): Unit = {
//1、读取数据
val lines: List[String] = Source.fromFile("scala/data/students.txt").getLines().toList
//2、取出班级
val classs: List[String] = lines.map(line => line.split(",")(4))
//3、按照班级进行分组
val group: Map[String, List[String]] = classs.groupBy(clazz => clazz)
//4、统计班级的人数
val countMap: Map[String, Int] = group.map(kv => {
val clazz: String = kv._1
val values: List[String] = kv._2
//计算班级的人数
val count: Int = values.size
(clazz, count)
})
//打印结果
countMap.foreach(println)
// select clazz,count(1) from student group by clazz
// sql 执行流程:
// from --> join on --> where --> group by --> having --> select --> order by --> limit
}
}
隐式转换(implicit)
package com.shujia.scala
object Demo23Implcat {
def main(args: Array[String]): Unit = {
// 显示转换(类型的转换)
val s: String = "100"
val i: Double = s.toDouble
/**
* 隐式转换
* 1、隐式转换方法
* 2、隐式转换变量
* 3、隐式转换类
*
*/
/**
* 1、隐式转换方法
*
* 隐式转换方法和方法名无关
* 和参数类型返回值类型有关,同一个作用域中只能存在一个参数类型和返回值类型一样的隐式转换
*/
implicit def stringToInt(str: String): Int = {
println("隐式转换方法被调用")
Integer.parseInt(str)
}
def fun(i: Int) = {
println(i + 100)
}
fun(1000)//1100
//显示类型转换
fun(Integer.parseInt("100"))//200
//自动调用隐式转换方法实现类型转换 (原类型和目标类型能够匹配上,就自动调用转换)
fun("123")
//相当于
fun(stringToInt("2000"))
implicit def intToString(i: Int): String = {
i.toString
}
/**
* 隐式转换: 动态给对象增加方法
*
*/
val j = 1000
val split: Array[String] = j.split(",")
}
}
package com.shujia.scala
object Demo24implicit {
def main(args: Array[String]): Unit = {
/**
* 隐式转换变量
*
* 同一个作用域中只能存在一个类型一样的隐式转换变量
*/
def fun(str: String)(implicit per: String) = {
println(str + "\t" + per)
}
//隐式转换变量
implicit val s: String = "后缀"
fun("java")("spark")//java spark
//自动使用隐式转换变量
fun("scala")//scala 后缀
}
}
package com.shujia.scala
import scala.io.Source
object Demo25implicit {
def main(args: Array[String]): Unit = {
// 隐式转换类
val lines: List[String] = "scala/data/students.txt".read()//直接通过字符串.的方式
lines.foreach(println)
val words: List[String] = "scala/data/words.txt".read()
words.foreach(println)
}
/**
* 隐式转换类
*
* 可以将ReadFile构造函数参数的类型转换成ReadFile
*/
implicit class ReadFile(path: String) {
def read() = {
Source.fromFile(path).getLines().toList
}
}
}