首页 > 其他分享 >Scala入门

Scala入门

时间:2024-07-10 15:30:07浏览次数:17  
标签:String val Scala Int foreach println def 入门

Scala

Scala特点:

  • 和 Java 无缝整合,满足各自语法基础上调用 Java 库;
  • 类型推断,类似于 Golang,Scala 通过 val 声明常量,通过 var 声明变量。
  • 支持并行和分布式;
  • 高阶函数编程,可以理解为面向对象编程,但是函数可以作为对象并当作参数传入。

数据类型

img

  • Null:代表空值,是 AnyRef 的子类;
  • Nothing:所有类型的子类,用于类型推断时不确定类型定义;
  • Unit:无返回值的函数的类型,对标 void;
  • Nil:长度为 0 的 List;

使用规则:

  • 区别 Object、Class,Object 可以理解为 Java代码中的单例(工具类),Class 理解为普通的类,程序加载时会预先加载 Object 中的方法;
  • Scala 中定义变量使用 var,定义常量使用 val,定义变量和常量不可以省略标识符,但是类型可以省略,系统会自动推断;
  • Scala 中每行后面会有分号自动推断机制;
  • Scala 中可以传参,传参必须指定类型,有了参数就会自动生成默认构造函数,类中地属性默认会有 setter、getter 方法;
  • 类中重写构造时,重写构造函数定义格式为 def this(....) {....},函数体第一行必须调用默认构造;
  • Scala 中当使用 new 对象 时,类中除了方法不执行【除了构造方法外】,其他方法都执行。
  • 在同一个 scala 文件中,class 名称和 Object 名称一样时,这个类叫做对象的伴生类,这个对象叫做这个类的伴生对象,之间可以相互访问私有变量。
  • 方法定义时:
    • 如果最后使用 return,那么方法返回值类型一定要指定;如果方法体中没有 return,默认将方法中最后一行结果返回,此时可以省略方法返回类型,会自动进行推断;
    • 定义方法时,如果省略了方法名称和方法体之间的 “=”,那么无论方法计算的结果是什么,都会丢弃返回空。
    • 递归方法需要显式地声明返回值类型。

特殊函数类型

匿名函数

函数可以看作变量,类似于 Golang 中函数使用方式。

def fun3(s:String*): Unit = {
    s.foreach(er => {
        println(er)
    })
}

def funObj = (a:Int, b:Int)=>{
a+b
}

偏应用函数

某些场景下,函数有很多个参数而且会被调用很多次,为了避免调用函数时重复写无关参数,可以定义偏应用函数,定义时经常变化的参数位置用 _:type 占位。

def log(date:Date, s:String) = {
    println(s"data is $date, log is $s")
}

val date = new Date()
val logWithDate = log(date, _:String)
logWithDate("log1")
logWithDate("log2")
logWithDate("log3")

高阶函数

  • 将函数作为参数,传入数据的同时传入处理逻辑,在类似 Spark 处理过程中的使用模式:
def fun4(f:(Int, Int)=>Int, s:String): String = {
    val i = f(100, 200)
    i + "#" + s
}
  
val nRes = fun4((a:Int, b:Int)=>{a*b}, "scala")
println(nRes)
  • 函数作为返回值,必须显示定义返回类型:
def fun5(s:String): (String, String)=>String = {
    def funInner(s1:String, s2:String): String ={
        s1 + "#" + "s2"
    }
    funInner
}
  • 函数参数和返回值均为函数类型:
def fun6(f:(Int, Int)=>Int): (String, String)=>String = {
    val i = f(1,2)
    def fun1(s1:String, s2:String): String = {
        s1 + "@" + s2 + "*" + i
    }
    fun1
}

字符串和集合

数组——Array

注意 Array 是不可变的,ArrayBuffer 是可变的。

object Lesson_Obj3 {
  def main(args: Array[String]): Unit = {
    // 定义并初始化赋值
    val arr1 = Array[String]("1", "2", "3")

    val arr2 = Array[String]("101", "102", "103")

    // 定义二维数组
    val arr3 = new Array[Array[String]](3)
    arr3(0) = Array[String]("1", "2", "3")
    arr3(1) = Array[String]("1", "2", "3")
    arr3(2) = Array[String]("1", "2", "3")
    for (outer <- arr3; elem <- outer) {
      println(elem)
    }

    arr3.foreach(elem=>{elem.foreach(println)})

    // 拼接两个数组
    val newArr = Array.concat(arr2, arr1)
    newArr.foreach(println)

    // 填充生成新数组
    Array.fill(4)("hello")

    // 生成可变的 ArrayBuffer
    val arrbuf = new ArrayBuffer[Int]()
    arrbuf.+=(1)
    arrbuf.+=:(100)
    arrbuf.foreach(println)
    arrbuf.append(5, 6, 7)
  }
}

集合——List

注意 List 是不可变的,ListBuffer 是可变的。List 支持 map()/count()/filter()/flatMap() 等方法来处理集合。

object Lesson_Obj4 {
  def main(args: Array[String]): Unit = {
    // 定义集合并初始化,默认元素类型是 Any
    val list = List(1, 2,3,"A", true)
    list.foreach(println)

    val list2 = List[String]("str1 1", "str2 2", "str3 3")
    val result = list.+("str4")
    println(result)

    val list3 = list2.map(s => {
      s.split(" ")
    })
    list3.foreach(arr => {
      arr.foreach(println)
    })

    val list4 = list2.flatMap(s => {s.split(" ")})
    list4.foreach(println)

    val list5 = list2.filter(s => {
      s.equals("str3 3")
    })
    list5.foreach(println)

    val num = list2.count(s => {
      s.length > 4
    })

    // 可变List
    val changeList = ListBuffer[String]("change1", "change2", "change3")
    changeList.append("change4")
  }
}

唯一集合——Set

注意集合的可变与不可变,默认是不可变集合,如果要使用可变集合,在定义时需要这样声明 mutable.Set

object Lesson_Obj5 {
  def main(args: Array[String]): Unit = {
    val set1 = Set[Int](1, 2, 1, 3, 4)
    set1.foreach(println)

    for (elem <- set1) {
      println(elem)
    }

    val set2 = Set[Int](4,5,6,1,2)
    val res1 = set2.intersect(set1)
    res1.foreach(println)

    val res2 = set2.diff(set1)
    res2.foreach(println)

    val res3 = set1 & set2

    // 可变长Set
    import scala.collection.mutable.Set
    val set3 = Set[Int](1,2,3,4)
    set3.+= (100)
    set3.+= (101, 102, 103)
    set3.foreach(println)

    val set4 = mutable.Set[Int](1,2,3,4,5,6)
  }
}

键值对集合——Map

Map 同上也区分可变不可变。

object Lesson_Obj6 {
  def main(args: Array[String]): Unit = {
    val map = Map[String, Int]("a"->100, "b"->101, "c"->102)
    map.foreach(println)

    val option = map.get("a")
    println(option)
    val option1 = map.get("aa")
    println(option1)
    val value = map.get("a").get
    println(value)
    val defaultVal = map.get("a").getOrElse("no value")
    println(defaultVal)

    // 根据Keys 获取 Value
    val keys = map.keys
    keys.foreach(key => {
      val tmp = map.get(key).get
      println(s"key = $key, value = $tmp")
    })

    // 操作 Values
    val values = map.values
    values.foreach(println)

    val map2 = Map[String, Int](("a", 1), ("b", 2), ("c", 3))
    map2.foreach(println)

    // 合并 Map
    val map3 = Map[String, Int](("a", 100), ("d", 200), ("c", 300))
    map3.foreach(println)
    val map4 = map2.concat(map3)
    map4.foreach(println)

    // 可变 Map
    val changeMap = mutable.Map[String, Int](("a", 1), ("b", 2), ("c", 3))
    changeMap.foreach(println)

    // 过滤 Map
    val map5 = changeMap.filter(kv => {
      val key = kv._1
      val values = kv._2
      value == 2
    })
    map5.foreach(println)
  }
}

元组——tuple

元组类似于 List,只不过元素默认为任意值。

object Lesson_Obj6 {
  def main(args: Array[String]): Unit = {
    val tuple = Tuple1[String]("hello")
    val tuple2 = new Tuple2("a", 100)
    val tuple3 = Tuple3(1, true , "c")
    val tuple4 = Tuple4(1, 3, 4, "a")
    val tuple5 = Tuple5(1, 1, 1, 1, "2")

    // 遍历元组
    val iterator = tuple5.productIterator
    while (iterator.hasNext) {
      println(iterator.next())
    }

    iterator.foreach(println)
  }
}

Trait

Trait 可以理解为接口或者抽象类,Trait 中的方法可以实现或者不实现。其他类继承 Trait 时要注意实现相应方法。

object Lesson_Obj7 {
  def main(args: Array[String]): Unit = {
    val p = new Human()
    p.read("张三")
    p.listen("李四")

    val p1 = new Point(1, 2)
    val p2 = new Point(3, 4)
  }
}

trait Read {
  def read(name:String) = {
    println(s"$name is reading")
  }
}

trait Listen {
  def listen(name:String) = {
    println(s"$name is listening")
  }
}

class Human() extends Read with Listen{
}

class Point(x:Int, y:Int) extends isEqual {
  val xx = x
  val yy = y

  // 重写 isEqual 方法
  override def equal(o: Any): Boolean = {
    o.isInstanceOf[Point] && o.asInstanceOf[Point].x == this.x
  }
}

// trait 定义方法但是未实现
trait isEqual {
  def equal(o:Any): Boolean

  def notEqual(o:Any): Boolean = !equal(o)
}

模式匹配

Scala 中 Match 匹配:

  • Math 理解为 Swtich,其中case_ 相当于 default,放在最后;
object Lesson_Obj8 {
  def main(args: Array[String]): Unit = {
    val tp = (1, 2, 3, "a", "abc", true)
    val iter = tp.productIterator
    iter.foreach(MatchTest)
  }

  def MatchTest(o:Any) = {
    o match {
      case 1 => println("value is 1")
      case i:Int => println("type is Int")
      case d:Double => println("type is Double")
      case s:String => println("type is String")
      case 'c' => println("type is Char")
      case _ => println("no match...")
    }
  }
}

偏函数,只能用于匹配一个值并且在匹配上了返回某个值:

def partialMatch :PartialFunction[String, Int] = {
    case "abc" => 2
    case "a" => 1
    case _ => 200
}

val result = partialMatch("abc")

隐式值与隐式转换函数

隐式值

隐式值是指在定义参数时在前面加上 implicit,方法中部分参数通过 implicit 来修饰。隐式值的作用就是使用函数时,不必手动传入部分隐式值参数,Scala 会自动在作用域范围内查找隐式值并自动传入。

// 函数参数使用隐式参数
def PartialFunction2(age:Int)(implicit name:String): Unit = {
    println(s"name is $name, age is $age")
}

def main(args: Array[String]): Unit = {
    val r = new Rabbit("rabbit")
    r.canFly()

    // 定义隐式值
    implicit val name = "zhagnsan"
    PartialFunction2(100)
}

注意:

  • 同类型的参数的隐式值只能在作用域内出现一次,同一个作用于不能定义多个隐式值;
  • 如果函数带有多个参数,部分参数定义为隐式值,那么这些参数需要单独 implicit 定义;
  • 一个方法只有一个参数是隐式转换参数时,可以直接定义 implicit 关键字修饰的参数,调用时直接创建类型不传入参数即可;
  • 一个方法如果有多个参数,其中部分是隐式参数,此时隐式关键字必须出现在后面,且只能出现一次。

隐式转换函数

隐式转换函数即通过 implicit 修饰的函数,作用于一些特定的使用场景。比如类A 想要调用 类B 的方法,不能直接调用,此时如果定义了隐式转换函数,系统会在调用方法时自动查找能否转换。

object Lesson_Obj9 {
  // 隐式转换函数
  implicit def RabbitToAnimal(r:Rabbit): Animal = {
    new Animal(r.name)
  }

  def main(args: Array[String]): Unit = {
    // Rabbit 类对象想要调用 Animal 类的方法,不可以直接调用
    val r = new Rabbit("rabbit")
    r.canFly()
  }
}

class Rabbit(xname:String) {
  val name = xname
}

class Animal (xname:String){
  val name = xname
  def canFly() = {
    println(s"$name can fly")
  }
}

Actor Model

Actor Model 是用来编写并行计算或者分布式系统的高层次抽象,避免程序员为多线程编程下共享锁问题影响。

标签:String,val,Scala,Int,foreach,println,def,入门
From: https://www.cnblogs.com/istitches/p/18294165

相关文章

  • 入门PHP就来我这(高级)20 ~ 事务处理
    有胆量你就来跟着路老师卷起来! --纯干货,技术知识分享路老师给大家分享PHP语言的知识了,旨在想让大家入门PHP,并深入了解PHP语言。 接着上篇我们来看下PDO数据库的事务处理。1PDO中的事务处理1.1事务相关概念事务(transaction)是由查询和更新语句的序列组成。用beg......
  • SpringBoot 入门
    步骤1:创建maven工程创建一个空Maven工程,如下:步骤2:pom.xml文件中添加SpringBoot依赖需要添加SpringBoot项目父级依赖和SpringBoot项目相关依赖,pom.xml内容如下:<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"......
  • Unity入门之重要组件和API(4) : Input
    前言Input类主要处理用户输入设备相关操作;输入设备包括鼠标、键盘、触屏、手柄、陀螺仪(重力感应)。1.鼠标1.1鼠标在屏幕的位置print(Input.mousePosition);1.2检测鼠标输入0-左键1-右键2-中键if(Input.GetMouseButtonDown(0)){ print("鼠标按下");}if(Input......
  • VBA编程:从入门到高手之路
    引言VisualBasicforApplications(VBA)是MicrosoftOffice套件中内置的编程语言,广泛用于自动化办公任务,特别是在Excel中。本文将带您从VBA的基础知识开始,逐步深入到高级技巧,助您成为VBA编程高手。1.VBA基础1.1什么是VBA?VBA是一种事件驱动的编程语言,允许用户......
  • SpringBoot 整合 MyBatisPlus框架入门
    步骤1:创建maven工程创建一个空Maven工程,如下:步骤2:pom.xml文件中添加MyBatisPlus相关依赖<dependencies><!--mybatispulus依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter&l......
  • ArcTs布局入门05——栅格布局(GridRow/GridCol)
    如果你也对鸿蒙开发感兴趣,加入“Harmony自习室”吧扫描下面的二维码关注公众号。1、概述栅格布局是一种通用的辅助定位工具,对移动设备的界面设计有较好的借鉴作用。主要优势包括:提供可循的规律:栅格布局可以为布局提供规律性的结构,解决多尺寸多设备的动态布局问题。通过将......
  • [C++入门]基础与语法
    1.数据类型C++作为一种强类型语言,支持多种数据类型,这些数据类型用于声明变量、函数参数、返回值等。数据类型可以分为两大类:基本数据类型和复合数据类型。基本数据类型整型(IntegerTypes):包括int(基本整型)、short(短整型)、long(长整型)、longlong(超长整型)、char(字符型,虽常作为......
  • Java基础入门了解,规范----入门篇1
    一.Java代码规范1.注释注释分类:1.单行注释:// 2.多行注释:/**/ 3.文档注释:/***/2.关键字java本身定义的一些单词,类似于public,class之内3.标识符在程序中定义的属性名,方法名,类名等等1.硬性要求:可以包含英文字母,0-9数字,$,_不能以数字开头关键字不能作为标识符2.软性......
  • 练习10.7_加法计算器_Python编程:从入门到实践(第3版)
    将为练习10.6编写的代码放在一个while循环中,让用户在犯错(输入的是文本而不是数)后能够继续输入数。#10.6try:expectwhileTrue:num1=input("请输入一个整数:")try:num1_int=int(num1)breakexceptValueError:print("......
  • Gradle基础:从入门到掌握
    人不走空                                          ......