zoukankan      html  css  js  c++  java
  • Scala入门笔记二

    标识符

    可用的字符

    • 处理括号类字符,分隔符之外,其他所有的可打印的ASCII字符,如字母,数字,下划线和美元符号($)均可出现在Scala标识符中
    • 插入符包括了(,) [,] {,and}
    • 分隔符包括 ` ' " . ; ,等
    • Scala还允许在标识符中使用编码在 u0020到u007F之间的字符,如数学符号,想 / 和 < 这样的操作符字符以及其他的一些符号

    不能使用保留字.

    普通标识符

    • 常见的标识符往往由字母或下划线开头,后面跟着一些字母,数字,下划线和$符
    • Scala允许使用Unicode格式的字符
    • $符在Scala内部会作为特定作用,尽量不要使用
    • Scala编译器会将下划线之后,空格之前的所有字符视为标识符的一部分
    • 假如在下划线后输入了操作符,那么不允许在操作符后输入字母或数字
    • 假如某一标识符以操作符开头,那么后面的字符也必须是操作符字符

    示例

    val xyz_++= = 1
    

    使用反引号定义标识符

    可以通过反引号定义标识符,两个反引号内的任意长度的字符串便是定义的标识符.

    def `test that addition work`= assert(1 + 1 = 2)
    

    无参数方法

    • 对于不包含参数的方法,除了可以选择使用中缀调用或后缀调用方式之外,Scala还允许用户灵活决定是否使用括号
    • 定义无参方法时省略了括号,那么在调用这些方法时必须省略括号
    • 定义无参方法时添加了空括号,那么调用该方法时可以选择省略或保留括号

    几个等价表达式

    List(1, 2, 3, 4).filter((i: Int) => isEven(i)).foreach((i: Int) => println(i))
    List(1, 2, 3, 4).filter(i => isEven(i)).foreach(i => println(i))
    List(1, 2, 3, 4).filter(isEven).foreach(println)
    List(1, 2, 3, 4) filter isEven foreach println
    

    优先级规则

    1. 所有字母
    2. |
    3. ^
    4. &
    5. < >
    6. = !
    7. :
    8. + -
    9. * / %
    10. 其他特殊字符
    
    • 所有操作符都是方法
    • 并不是所有方法都是左结合
    • 任何名字以冒号(:)结尾的方法均与其右边的对象绑定

    cons操作

    • cons是constructor的缩写
    • cons操作指通过::方法将某一元素放置到列表前面

    示例

    scala> val list = List('c', 'd')
    list: List[Char] = List(c, d)
    
    scala> 'a' :: list
    res1: List[Char] = List(a, c, d)
    
    scala> val list = List('c', 'd')
    list: List[Char] = List(c, d)
    
    scala> 'b' :: list
    res2: List[Char] = List(b, c, d)
    
    scala> list.::('a')
    res3: List[Char] = List(a, c, d)
    
    scala> 'a' :: list
    res4: List[Char] = List(a, c, d)
    
    scala> 'b' :: list
    res5: List[Char] = List(b, c, d)
    

    注意:

    • 'a' :: list 等价于 list.::('a')

    • 不能使用该方法重复插入多个字符

    if语句

    • Scala的if语句可以向Java中一样使用

      if (2 + 2 = 5) {
      	println("if")
      } else if (2 + 2 = 3) {
      	println("else if")
      } else {
      	println("else")
      }
      
    • Scala中的if语句是有返回值的. 可以将if表达式的结果值赋值给其他变量. 以下面代码为例.

      val configFile = new java.io.File("someFile.txt")
      
      val configFilePath = if (configFile.exists()) {
      	configFile.getAbsolutePath()
      } else {
          configFile.createNewFile()
      	configFile.getAbsolutePath()
      }
      

      if语句返回值的类型也被称为所有条件分支的最小上界类型,也就是与每条each子句可能返回值类型最接近的父类型.在上面例子中,configFilePath 是if表达式的结果值,该if表达式将执行文件不存在的条件分支(假定),并返回新创建文件的绝对路径.将if语句的返回值赋予变量configFilePath .

    Scala不支持三元表达式

    循环

    for推导式

    for循环

    示例

    代码
    val list = List("A", "B", "C")
      
    for (item <- list)
        println(item)
    
    输出
    A
    B
    C
    

    生成器表达式

    • item <- list这样的表达式被称为生成器表达式
    • 该表达式会基于集合生成单独的数值
    • 左箭头操作符(<-)用于对象列表这样的集合进行遍历

    保护式: 筛选元素

    • for语句中可以加入if表达式来筛选元素,这些表达式被称为保护式(guard)

    示例

    代码
    val list = List("ABC", "CDE", "EFG")
    
    for (item <- list
        if item.contains("C")
        )
      println(item)
    
    输出
    ABC
    CDE
    

    添加多个保护式

    示例
    val list = List("ABC", "BCD", "CDE")
      
    for (item <- list
       if item.contains("B")
       if !item.startsWith("A")
        )
      println(item)
     
    for (item <- list
       if item.contains("B") && !item.startsWith("A")
        )
      println(item)
    
    输出
    BCD
    BCD
    
    • 分别为两个for循环的输出

    Yielding

    • 使用yielding关键字能在for表达式中生成新的集合

    示例

    代码
    val list = List("ABC", "BCD", "CDE")
    val filterItems =  for {item <- list
    	if item.contains("B")
     	if !item.startsWith("A")
    	} yield item
    filterItems
    
    运行
    scala> val list = List("ABC", "BCD", "CDE")
    list: List[String] = List(ABC, BCD, CDE)
    
    scala> val filterItems =  for {item <- list
         | if item.contains("B")
         |  if !item.startsWith("A")
         | } yield item
    filterItems: List[String] = List(BCD)
    

    扩展作用域与值定义

    • 能够在for表达式中的最初部分定义值,并可在以后的表达式中使用该值

    示例

    代码
    val list = List("abc", "bcd", "cde")
      
    val upcaseItems = for {
    	item <- list
        upcaseItem = item.toUpperCase()
    } yield upcaseItem
    
    运行
    scala> val list = List("abc", "bcd", "cde")
    list: List[String] = List(abc, bcd, cde)
    
    scala>
         | val upcaseItems = for {
         | item <- list
         |     upcaseItem = item.toUpperCase()
         | } yield upcaseItem
    upcaseItems: List[String] = List(ABC, BCD, CDE)
    

    while循环

    示例

    while (表达式) {
    	do something
    }
    

    do...while循环

    示例

    var count = 0
    do {
    	count += 1
    } while(count < 10)
    

    条件操作符

    操作符 操作
    && 和操作
    || 或操作
    > 大于
    >= 大于或等于
    < 小于
    <= 小于或等于
    == 等于
    != 不等于
    • &&|| 是短路操作符

    • 在Java中== 只会对对象引用进行比较, 调用equals来比较字段值; Scala使用== 符执行逻辑上的相等检查. 即调用equals方法进行判断.

      public class Person {
          private String name;
          private int age;
          public Person(String name, int age) {
              this.name = name;
              this.age = age;
          }
      
          public boolean equals(Object obj) {
              return true;
          }
      
          public static void main(String args[]) {
              Person p1 = new Person("sun", 20);
              Person p2 = new Person("li", 20);
              System.out.println(p1 == p2);
          }
      }
      // 输出:
      false
      
      class Person(var name: String, var age: Int) {
          override def equals(obj: scala.Any): Boolean = true
      }
      
      val p1 = new Person("sun", 20)
      val p2 = new Person("sun", 20)
      
      println(p1 == p2)
      
      // 输出:
      true
      

    使用try...catch...final子句

    • Scala使用模式匹配来捕获异常, 而Java使用单独的catch子句来捕获各个异常
    • 使用case NonFatal(ex) => ... 子句使用scala.util.control.NonFatal 匹配了所有的非致命性异常
    • 通过编写throw new MyBadException(...) 抛出异常
    • 如果自定义异常是一个case类,那么抛出异常时可以省略new关键字

    实例

    try {
    	...
    } catch {
    	case NonFatal(ex) => println(s"Non fatal exception! $ex")
    	case ...
    } finally {
    	...
    }
    

    惰性赋值

    • 惰性赋值是与传名参数相关的技术
    • 如果希望以延迟的方式初始化某值, 并且表达式不会被重复计算, 则需要使用惰性赋值
    • 常见应用场景
      • 由于表达式执行代价昂贵(比如打开一个数据库连接), 希望能推迟该操作, 直到确实需要表达式结果时才执行它
      • 为了缩短模块启动时间, 可以将当前不需要的某些工作推迟执行
      • 为了确保对象中其他字段的初始化过程能优先执行, 需要将某些字段惰性化

    示例

    object ExpensiveResource {
    	lazy val resource: Int = init()
    	def init(): Int = {
    		// 某些代价昂贵的操作
    		0
    	}
    }
    
    • lazy关键字意味着求值过程会被推迟,只有需要时才会执行计算
    • 首次使用惰性值时, 初始化代码才会被执行一次, 这种只能执行一次的计算对于可变字段而言没有任何意义.因此lazy关键字不能修饰var变量
    • 通过**保护式来实现惰性值

    枚举

    • Scala通过在标准库中专门定义Enumeration类实现枚举

    示例一

    代码

    // file: enum.scala
    object Breed extends Enumeration {
        type Breed  = Value
        val doberman    = Value("Doberman Pinscher")
        val yorkie      = Value("Yorkshire Terrier")
        val scottie     = Value("Scottish Terrier")
        val dane        = Value("Great Dane")
        val portie      = Value("Portuguese Water Dog")
    }
    
    import Breed._
    
    println("ID	Breed")
    for (breed <- Breed.values) println(s"${breed.id}	$breed")
    
    println("
    Just Terriers:")
    Breed.values filter (_.toString.endsWith("Terrier")) foreach println
    
    def isTerrier(b: Breed) = b.toString.endsWith("Terrier")
    
    println("
    Just Terriers:")
    Breed.values filter isTerrier foreach println
    

    运行

    scala enum.scala

    输出

    ID      Breed
    0       Doberman Pinscher
    1       Yorkshire Terrier
    2       Scottish Terrier
    3       Great Dane
    4       Portuguese Water Dog
    
    Just Terriers:
    Yorkshire Terrier
    Scottish Terrier
    
    Just Terriers:
    Yorkshire Terrier
    Scottish Terrier
    

    可插入字符串

    下面是一个简单示例:

    val name = "Buck Trends"
    println(s"Hello, $name")
    

    格式化

    下面是几个对可插入字符串进行格式化的示例.

    scala> val gross = 100000F
    gross: Float = 100000.0
    
    scala> val net = 64000F
    net: Float = 64000.0
    
    scala> val percent = (net / gross) * 100
    percent: Float = 64.0
    
    scala> println(f"$$${gross}%.2f vs. $$${net}%.2f or ${percent}%.1f%%")
    $100000.00 vs. $64000.00 or 64.0%
    
    scala> val s = "%02d: name = %s".format(5, "Dean Wampler")
    s: String = 05: name = Dean Wampler
    
    // 原生插入器
    scala> val name = "Dean Wampler"
    name: String = Dean Wampler
    
    scala> s"123
    $name
    456"
    res1: String =
    123
    Dean Wampler
    456
    
    scala> raw"123
    $name
    456"
    res2: String = 123
    Dean Wampler
    456
    
    • 使用$$ 打印一个$
    • 使用%% 打印一个%
  • 相关阅读:
    (双指针 二分) leetcode 167. Two Sum II
    (双指针) leetcode 485. Max Consecutive Ones
    (双指针) leetcode 27. Remove Element
    (String) leetcode 67. Add Binary
    (数组) leetcode 66. Plus One
    (N叉树 BFS) leetcode429. N-ary Tree Level Order Traversal
    (N叉树 递归) leetcode 590. N-ary Tree Postorder Traversal
    (N叉树 递归) leetcode589. N-ary Tree Preorder Traversal
    (N叉树 DFS 递归 BFS) leetcode 559. Maximum Depth of N-ary Tree
    (BST 递归) leetcode98. Validate Binary Search Tree
  • 原文地址:https://www.cnblogs.com/bovenson/p/5803560.html
Copyright © 2011-2022 走看看