语法学习
# Scala中,一切皆为对象
# 需要注意的
- 定义多个变量 var (i,j,temp) = (1, 0, 0)
- 记住: 除了循环都没有返回值,其余都有返回值
- 函数化编程: 函数即参数
//例如 (遍历元组)
tuple22.productIterator.foreach(i => print(i + " "))
- break语句
// 创建 Breaks 对象
val loop = new Breaks;
// 在 breakable 中循环
loop.breakable{
// 循环
for(...){
....
// 循环中断
loop.break;
}
}
- foreach和迭代器的区别
foreach遍历元素类型相同的 (例如 数组) 迭代器用来遍历元素类型不同的 (例如 元组. Map集合?)
# 运算符
object MyScala{
def main(args:ArrayString]){
val num:Int = 195
println(s"${num<<2}\r${num>>2}\r${num>>>2}")
}
}
# 字符串函数
# 流程控制语句
package com.hrbu.nscala
import scala.io.StdIn
object ControlStatement {
def test1(): Any = {
val in = StdIn.readLine("请输入: ")
//用if实现java三元表达式
println(if(in.isInstanceOf[Int]) in.toString() else "字符串:" + in )
return if(in.isInstanceOf[Int]) in.toString() else in
}
def test2():Any = {
print("请输入:")
val in = StdIn.readInt()
return if(in.isInstanceOf[Int]){
println("类型正确")
} else{
println("类型不正确")
}
}
/*
* 2.to and until
*/
def test3{
val r1 = 1 to 10
val r2 = 1 until 10
val r3 = 1 to (10,2) // a.步长
println(r1 + "\n" + r2 + "\n" + r3)
}
/*
* 3.循环语句
* a.for
*/
def test4{
for (i <- 1 to 4) {
println(i)
}
//乘法表
/*for(i<- 1 until 10){
for(j<- 1 until 10){
if(i>=j){
print(s"$i * $j=" + i*j + "\t")
}
if(i==j){
println()
}
}
}*/
//简化
/*for(i<- 1 until 10;j<- 1 until 10){
if(i>=j){
print(s"$i * $j=" + i*j + "\t")
}
if(i==j){
println()
}
}*/
}
/**
* while
* do...while
*/
def test5{
var b: Int = 0
while (b < 10) {
println(s"第$b 次求婚") //r 注意$b后一定有空格
b += 1
}
}
/**
* 4.yield关键字:记住每次迭代中的有关值,并逐一存入到一个数组
* 5.循环过滤 (遍历数组)
*/
def test6{
val result = for { i <- 1 to 100 if (i > 50) if (i % 5 == 0) } yield i
//val result = for(i<- 1 to 100 if(i>50) if(i%5==0)) yield i
println(result)
}
def main(args: Array[String]): Unit = {
println("test1返回: " + test1())
println("test2返回值: " + test2())
println("println语句返回值:" + println("nicai"))
}
}
# 方法和函数
# 1.普通方法
def 方法名 (参数:参数类型):方法返回值={函数体}
def max1(a:Int,b:Int):Int={
if(a>b){
return a
} else{
println("b>a")
return b
}
}
println("max1=" + max1(b=69, a=35))
/*****简化上面的方法**方法体如果可以一行搞定,可去掉{}*****/
def max1_1(a:Int,b:Int) = if(a>b) a else b
println("max1.1=" + max1_1(12, 9))
# 2.递归方法
递归方法要显式的指定函数的返回值类型
def factorial(num:Int):Int = {
if(num == 1){
1
} else {
num * factorial(num-1)
}
}
println(s"5的阶乘为: ${factorial(5)}")
# 3.带默认参数的方法
def max3(a:Int=69, b:Int=66) = if (a>b) a else b
println("max3= " + max3())
println("max3= " + max3(b=100))
# 4.可变长参数的方法
def showStr(str:String*){
for(elem <- str){
print(elem)
}
}
showStr("Hello", " ", "Scala", "\r");
showStr("长河落日东都城", ",", "铁马戍边将军坟", "。", "尽诛宵小天策义", ",", "长枪独守大唐魂", "。", "\n")
/***************方法简化**************/
def showStr(str:String*) = str.foreach(print)
# 5.匿名函数
"=>"就是匿名函数,多用于方法的参数为函数时,常用匿名函数
def max5() = (a:Int, b:Int)=>if (a>b) a else b
println(max5()(11, 22))
# 6.嵌套函数
def value6(num:Int):Int={
def factorial6(a:Int):Int = if(a == 1) 1 else a * factorial6(a - 1)
factorial6(num)
}
println("5的阶乘为: " + value6(5))
# 7.偏应用函数
某些情况下,方法中参数非常多,调用非常频繁,每次调用只有固定的一个参数变化,其它都不变,可以定义偏应用函数简化
//先定义一个普通函数
def showLogs(date:Date, log:String) = {
println(s"date = $date\tlog = $log")
}
val date: Date = new Date(); //注意:这里是scala变量
showLogs(date, "balabala") //普通函数调用
showLogs(date, "hahahaha")
//定义偏应用函数
def showLogs7 = showLogs(date:Date, _:String)
showLogs7("123456789")
showLogs7("987654321")
# 8.高阶函数
/**a.参数是函数的方法*/
/*def fun8_1(a:Int,b:Int)={
a+b
}*/
/*def fun8_a(f:(Int,Int)=>Int,s:String) : String={
val i:Int = f(100,200)
i+"#" +s
}
val result1 = fun8_a((a:Int,b:Int)=>{a*b},"Scala")
println(result1)*/
/**b.返回值是函数的方法*/
/*def fun8_b(s:String):(String,String)=>String={ //显示声明返回值(或最后一行写为fun _)
def fun(s1:String,s2:String):String={
s1 + " " + s2 + " " +s
}
fun //r 当返回值时不加括号
}
println(fun8_b("!!!")("Hello","Scala"))*/
/**c.返回值和参数都是函数的方法*/
/*def fun8_c(f:(Int,Int)=>Int):(String,String)=>String={
val fInt = f(1,2)
def fun8(s1:String,s2:String):String={
s1 + " " + s2 + fInt.toString()
}
fun9
}
println("返回值参数都是函数:" + fun9_c((a,b)=>{a+b})("Hello", "Scala"))*/
1.方法的参数是函数
/*a.参数是函数*/
def pet(pName:String, pAttack:Int): String = {
(s"宠物名字: ${pName}\t宠物攻击力: ${pAttack}")
}
def hero(fun:(String, Int) => String, heroName:String) = {
println(s"英雄名字: ${heroName}\t${fun("龙狼王", 10000)}")
}
hero(pet, "琴帝")
2.方法的返回是函数
/*b.返回值为参数*/
def hero2(heroName:String, heroAttack:Int) : (String, Int) => String = {
def getMessage(pName:String, pAttack:Int) : String = {
(s"英雄名字: ${heroName}\t宠物名字: ${pName}\t攻击力: ${heroAttack + pAttack}")
}
getMessage //注意 当返回值不加()
}
println(hero2("酒神", 10000)("阴阳冕", 8000))
3.方法的参数和返回值都是函数
def hoFun(f:(Int,Int)=>Int):(String,String)=>String={
val fInt = f(1,2)
def fun(s1:String,s2:String):String={
s1 + " " + s2 + fInt.toString()
}
fun
}
println("返回值参数都是函数:" + hoFun((a,b)=>{a+b})("Hello", "Scala"))
# 9.柯里化函数
返回值是函数的方法的简化
def fun9(a:Int, b:Int)(c:Int, d:Int) = a + b + c + d
println(fun9(250,50)(100,120))
# 数组
/*
* 1.第一种定义方式
*/
def ImmutableArray1{
val arr = Array[String]("Hello", "Scala", "Hello", "World");
arr.foreach(println)
}
/*
* 2.第二种定义方式
*/
def ImmutableArray2{
val arr = new Array[String](3);
arr(0) = "你好"
arr(1) = "世界"
arr(2) = "!!!"
//arr(3) = "" //java.lang.ArrayIndexOutOfBoundsException
arr.foreach(print)
}
/*
* 3.关于数组连接 fill方法
*/
def ImmutableArray3{
val arr1 = Array[String]("aaa", "bbb", "ccc")
val arr2 = Array[String]("333", "666", "999")
// println(arr1.contains(arr2))
Array.concat(arr1, arr2).foreach(print)
println()
val arr3 = Array.fill(6)("Scala")
arr3.foreach(print)
}
/*
* 4.二维数组
*/
def ImmutableArray4{
val arr = new Array[Array[String]](3)
arr(0) = Array[String]("Hello", "World", "!!!")
arr(1) = Array[String]("Hello", "Scala")
arr(2) = Array[String]("Hello", "Array", "EOF")
for(arrTemp <- arr; str <- arrTemp){
print(str + " ")
}
}
/*
* 5.可变数组 类似 java 的 ArrayList
*/
def MutableArray{
var arr = ArrayBuffer[String]("111", "222")
arr.foreach(i => print(i + " "))
// arr.+:("+:")
arr.+=("+=") //数组末插入
arr.+=:("+=:") //数组首插入
// arr.++("++")
// arr.++:("++:")
// arr.++=(Array("...", "***")) //用++=操作符追加任何集合
println()
arr.foreach(i => print(i + " "))
arr.append("aaa", "bbb", "ccc") //追加元素
println()
arr.foreach(i => print(i + " "))
}
# 元组
拉链
package com.hrbu.scala
/**
* 元组
*/
object Scala10_Tuple {
def main(args: Array[String]): Unit = {
//注意:tuple最多支持22个参数
/**1.创建*/
//val tuple = new Tuple1(1)
val tuple2 = Tuple2("zhangsan",2)
val tuple3 = Tuple3(1,2,3)
//val tuple4 = (1,2,3,4)
//val tuple18 = Tuple18(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)
val tuple22 = new Tuple22(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)
//使用
/*println(tuple2._1 + "\t"+tuple2._2)
val t = Tuple2((1,2),("zhangsan","lisi"))
println(t._1._2)*/
/***2.遍历*/
val tupleIterator = tuple22.productIterator
while(tupleIterator.hasNext){
println(tupleIterator.next())
}
/**
* 方法
*/
//翻转,只针对二元组
println(tuple2.swap)
//toString
println(tuple3.toString())
}
}
# 链表List
和Java里不同,Scala中List一定是以链表方式实现的。Java中的List概念对应Scala中的Seq。 链表的特征:元素有先后之分,适合逐个访问
package com.hrbu.scala
import scala.collection.mutable.ListBuffer
object Scala7_List {
def main(args: Array[String]): Unit = {
val list1 = List[Int](7,9,1,2,3,4,5,6)
/*for(i<-list1){
print(i + " ")
}*/
//list1.foreach(print)
/*for(i<-0 until list1.count(x=>true)){
print(list1(i) + " ")
}
println()*/
/*val countList1 = list1.count(x=>x>=3)
println(countList1)*/
/***********重要方法****************/
val list2 = List("hello world","hello scala","hello spark")
// 1.过滤:filter方法
//print(list1.filter(x=>x>=6).toString())
/*val list_ = list1.filter(x=>x>=6)
list_.foreach(println)*/
// 2.对元素操作:map方法
/*val list2_ = list2.map(x=>x.split(" "))
for(i<-list2_;j<-i){
println(j)
}*/
// 3.扁平化操作(压扁压平,先map再flat):flatMap方法
val list2_ = list2.flatMap(x=>x.split(" "))
for(elem<-list2_){
println(elem)
}
/**不可变数组***/
/**可变数组*/
/*val list = ListBuffer[String]("hello","scala")
list.+=("aaa","bbb")
list.foreach(println(_))*/
}
}
# Map
/*
* map练习
*/
def testMap{
val map1 = Map (
1 -> "hello",
"2" -> "scala",
(3, "kugou")
)
println(map1.get("2"))
println(map1.get(3))
// 1.若没有值,赋值为getOrElse传的值
println(map1.get("key").getOrElse("no value"))
/****2.遍历map*******/
//2.1 foreach 遍历
println("1.foreach 遍历:")
map1.foreach(
f => println("key=" + f._1 + "\tvalue=" + f._2)
)
//2.2 每次获取其中一个元组
println("每次获取其中一个元组:")
for(elem <- map1){
println("key:" + elem._1 + "\tvalue:" + elem._2)
}
//2.3 每次循环直接解析元组(析构)
println("每次循环直接解析元组:")
for((key,value) <- map1){
println(s"key:$key\tvalue:$value")
}
/****3.遍历key*****/
println("遍历key:")
// 1.map.keys为迭代器类型 2.keySet为Set类型
val keyIterable = map1.keys
for(elem<-keyIterable){
println("key:" + elem + "\tvalue:" + map1.get(elem).get)
}
/****4.遍历value****/
println("遍历value")
val valueIterable = map1.values
for(elem <- valueIterable){
println("value:" + elem)
}
// valueIterable.foreach {
// value => println("value: " + value)
// }
/*****5.合并map 合并时将相同key的value替换 ********/
val map2 = Map[Int,String](
(1,"hi"),
(2,"你好"), //此处2为Int,上面是String
(3,"世界"),
(4,"酷狗")
)
println("map1加入到map2中")
map1.++(map2).foreach(println) //map1加入到map2中
println("map2加入到map1中")
map1.++:(map2).foreach(println) //map2加入到map1中
/****6.可变map*****/
var map3 = scala.collection.mutable.Map(
"天策" -> "长河落日东都城,铁马戍边将军坟。尽诸宵小天策义,长枪独守大唐魂。",
"万花" -> "春兰秋菊夏清风,三星望月挂夜空。不求独避风雨外,只笑桃源非梦中。",
"纯阳" -> "昆仑玄境山外山,乾坤阴阳有洞天。只问真君何处有,不向江湖寻剑仙。",
"七秀" -> "西子湖畔西子情,楼外楼中雨霖铃。画廊绣舫霓裳舞,小桥流水叶娉婷。",
"少林" -> "古刹紫竹禅钟鸣,降妖伏魔江湖行。佛音亦有豪情意,天下武功出少林!",
"藏剑" -> "秀水灵山隐剑踪,不闻江湖铸青锋。逍遥此身君子意,一壶温酒向长空。",
"五毒" -> "蛇蝎为伴蛛为邻,千蝶绕笛蛊无形。世人皆惧断肠物,不见最毒在人心。",
"唐门" -> "蜀中世家纷争事,暗起云涌逍九天。针翎钉棘十指牵,暴雨飞星乾坤颠。",
"苍云" -> "雪覆胡关摧冷草,风扬朔漠起狼烟。刃端百死何辞战,碧血成书白马篇。",
"丐帮" -> "搅动君山五十州,风尘几历尽翩遥。散罢千金未束手,餐风吞酒不寂寥。",
"长歌" -> "儒门有志羁风雨,失鹿山河散若星。千古文人侠客梦,肯将碧血写丹青。",
"霸刀" -> "寥落尘寰数十载,何曾开眼论豪英。刀光起处鲸吞海,誓将浮名敬死生。"
)
/*删除元素*/
//map3.-=("唐门")
map3.remove("唐门")
//map3.foreach(f => println(f._1 + ":" + f._2))
/*增加元素*/
//map3.+=("唐门" -> "蜀中世家纷争事,暗起云涌逍九天。针翎钉棘十指牵,暴雨飞星乾坤颠。")
map3.put("唐门", "蜀中世家纷争事,暗起云涌逍九天。针翎钉棘十指牵,暴雨飞星乾坤颠。")
/*修改value*/
map3("苍云") = "歌起征思芦管怨,透穿玄甲朔风寒。黄泉作酒酬兄弟,战尽狂沙血未干。"
map3.foreach(f => println(f._1 + ":" + f._2))
/*
* 7.重要方法
* filter:过滤,留下符合条件的记录
* count:统计符合条件的记录数
* contains:map中是否包含某个key
* exist:符合条件的记录存在不存在
*/
}
# Set
package com.hrbu.scala
import scala.collection.mutable.Set
object Scala8_Set {
def main(args: Array[String]): Unit = {
// set无重复元素
/*val set1 = Set("hello","scala","hello","world")
set1.foreach(println)*/
val set2 = Set("hello","world","scala","spark")
val set3 = Set("hello","world","!!!","???","///")
/***********重要方法**************/
//1.求交集
/*val set_ = set2.intersect(set3)
for(elem<-set_){
println(elem)
}*/
//2.求差集
/*val set_ = set2.diff(set3)
for(elem<-set_){
println(elem)
}*/
//3.求是否是子集
//println(set2.subsetOf(set3))
//4.max.min
//println(set2.min)
//5.转成数组
/*val set_ = set2.toList
set_.foreach(println)
println(set_)*/
//6.转成字符串
val strSet = set2.mkString("+")
println(strSet)
/*********可变长****************/
val set4 = Set[String]("aaa","bbb")
set4.add("ccc")
set4.+=("elem1")
set4.foreach(println)
}
}
# 类继承和伴生对象
Student.scala
package com.hrbu.nscala
//子类 可继承父类的私有成员
class Student(name:String, age:Int, height:Int, weight:Double) extends Persion(name, age) {
//println("Student的构造方法")
val id = Student.getNumber()
val info = Student.info
override def sayMessage():String = {
s"$id\t${super.sayMessage()}\t$height\t$weight\t$info"
}
}
//父类
class Persion(name:String, age:Int) {
private var height:Int = _
private var weight:Double = _
//println("Persion的构造方法")
def sayMessage(): String = {
s"$name\t$age"
//s"name= $name\tage= $age\theight= $height\tweight= $weight"
}
}
//伴生对象 类似于静态类
object Student {
private var lastnumber:Int = 0
private var info:String = _
def apply(in:String) = {
info = in
}
def getNumber():Int = {
lastnumber += 1
lastnumber
}
}
Test.scala
package com.hrbu.nscala
object Test {
def main(args: Array[String]): Unit = {
val persion = new Persion("a", 24)
println(persion.sayMessage())
Student.apply("我们都是好孩子,最最善良的孩子")
val stu = Array[Student](
new Student("aaa", 22, 170, 65),
new Student("bbb", 25, 180, 75),
new Student("ccc", 24, 175, 73)
)
stu.foreach(f => println(f.sayMessage()))
//println(stu(0).sayMessage())
}
}
# 模式匹配和样例类
package com.hrbu.nscala
import scala.util.Random
object MatchAndClass {
/**
* 0.模式匹配和样例类
*/
/**
* _.模式匹配
* 1.模式匹配不仅可以匹配值还可以匹配类型
* 2.从上到下顺序匹配,如果匹配到则不再往下匹配
* 3.都匹配不上时,会匹配到case _ ,相当于default
*/
def matchTest(x:Any):Unit = {
x match {
case a:Int => println("参数为Int类型")
case 1 => println("值为 1") //匹配不到
case 2 => println("值为 2")
case b:String => println("参数为字符串类型")
case _ => print("未匹配到")
}
}
/**
* _.偏函数
* 1.如果一个方法中没有match 只有case,这个函数可以定义成PartialFunction偏函数。
* 2.偏函数定义时,不能使用括号传参,默认定义PartialFunction中传入一个值,匹配上了对应的case,返回一个值
*/
//PartialFunction的一个实例 [参数类型, 返回值类型]
def myTest: PartialFunction[String, Any] = {
case "Hello" => "Hello"
case "World" => println("World")
case "Scala" => "Scala"
case _ => "未匹配到"
}
def myTest2(num:Int) :String = num match {
case 1 => "First"
case 2 => "Second"
case 3 => "Third"
case _ => "未匹配到"
}
/**
* _. 样例类
* 1.概念
* 1.1使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类
* 1.2实现了类构造参数的getter方法(构造参数默认被声明为val),当构造参数是声明为var类型的,它将帮你实现setter和getter方法
* 1.3 case class是多例的,后面要跟构造参数,case object是单例的
* 2.注意
* 2.1 样例类默认帮你实现了toString,equals,copy和hashCode等方法
* 2.2 样例类可以new, 也可以不用new
*/
def classDemo(){
val arr = Array(new Stu("曹雪阳", 32), People)
arr(Random.nextInt(arr.length)) match {
case Stu(name, age) =>{
println(s"姓名:$name\t年龄:$age")
}
case People => {
println("People类")
}
}
}
/**
* Option类型用样例类来表示可能存在或也可能不存在的值(Option的子类有Some和None)
*/
def optionTest(x:String) = {
val map = Map{
"天策" -> "长河落日东都城,铁马戍边将军坟。尽诸宵小天策义,长枪独守大唐魂。"
}
//类似getOrElse()方法
map.get(x) match{
case Some(s) => s
case None => "?"
}
}
def main(args: Array[String]): Unit = {
//1.模式匹配
// matchTest(1)
//2.偏函数
// myTest("World")
// println(myTest("Scala"))
// println(myTest2(1))
//3.样例类
classDemo()
//option
println(optionTest("天策"))
println(optionTest("万花"))
}
}
# Scala 下划线(_) 用法汇总
# 1.导包时的通配符
import java.util._
类似Java的
import java.util.*
# 2.Scala类中成员变量初始化
class Foo{
//String类型的默认值为null 不适合局部变量
var s: String = _
}
# 3.类型通配符
Java的泛型系统有一个通配符类型,例如List<?>,任意的List类型都是List<?>的子类型,如果我们想编写一个可以打印所有List类型元素的方法,可以如下声明:
public static void printList(List<?> list){
for(Object elem: list){
System.out.println(elem + " ");
}
}
对应的Scala版本为:
def printList(list: List[_]): Unit ={
list.foreach(elem => println(elem + " "))
}
# 4.可变参数
Java声明可变参数如下:
public static void printArgs(String ... args){
for(Object elem: args){
System.out.println(elem + " ");
}
}
调用方法如下:
//传入两个参数
printArgs("a", "b");
//也可以传入一个数组
printArgs(new String[]{"a", "b"});
在Java中可以直接将数组传给printArgs方法,但是在Scala中,你必须要明确的告诉编译器,你是想将集合作为一个独立的参数传进去,还是想将集合的元素传进去。如果是后者则要借助下划线:
printArgs(List("a", "b"): _*)
# 5.模式匹配
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "anything other than one and two"
}
expr match {
case List(1,_,_) => " a list with three element and the first element is 1"
case List(_*) => " a list with zero or more elements "
case Map[_,_] => " matches a map with any key type and any value type "
case _ =>
}
List(1,2,3,4,5).foreach(print(_))
// Doing the same without underscore:
List(1,2,3,4,5).foreach( a => print(a))
在Scala中,在一个object中非私有变量的getter和 setter方法会被隐式定义好,getter方法名和变量名相同,我们可以使用_=自定义setter name,更好的控制赋值
class Test {
private var a = 0
def age = a
def age_=(n:Int) = {
require(n>0)
a = n
}
}
Usage:
val t = new Test
t.age = 5
println(t.age)
# 6.将函数赋给变量
如果尝试将函数直接赋值给一个变量,这个函数会被直接调用,并将调用的结果赋值给变量,如果在函数名称后面加上_,那么赋值的是函数体本身
class Test {
def fun = {
// Some code
}
val funLike = fun _
}
# 7.访问Tuple元素
val t = (1, 2, (7, 9))
println(t._1, t._2, t._3._1, t._3._2)
# 8.参数展开
def getConnectionProps = {
( Config.getHost, Config.getPort, Config.getSommElse, Config.getSommElsePartTwo )
}
如果客户端需要拿到所有连接参数
val ( host, port, sommEsle, someElsePartTwo ) = getConnectionProps
如果仅仅需要拿到host和port
val ( host, port, _, _ ) = getConnectionProps
# 9.其它用法——简化函数
val nums = List(1,2,3,4,5,6,7,8,9,10)
nums.filter (_ % 2 == 0)
nums.reduce (_ + _)
nums.exists(_ > 5)
nums.takeWhile(_ < 8)