scala学习笔记


java程序员的scala基础学习笔记,只记录了些基础知识。

hello world

package blog

object HelloWorld {
   /* 这是我的第一个 Scala 程序
    * 以下程序将输出'Hello World!' 
    */
   def main(args: Array[String]) {
      println("Hello, world!") // 输出 Hello World
   }
}

关键字转义

与关键字同名,需要转义,例

Thread.`yield`();

yield为关键字,需要加引号转义

数据类型

在这里插入图片描述

变量

scala可以算是弱类型的,用法与js中的有些相似。

var定义变量,val定义常量
      var a = 1;  //变量
      val b = 2;  //常量

scala同样支持强类型的定义方法

var a : Int = 1;

具体语法为

var VariableName : DataType [=  Initial Value]

或

val VariableName : DataType [=  Initial Value]
元组

在 Scala 中,元组是一个可以容纳不同类型元素的类。 元组是不可变的。
当我们需要从函数返回多个值时,元组会派上用场。

var py: (Int, String) = (40, "")

很python的感觉,就用py来命名了。

这东西感觉就像是另一种Object[]一样,只是多了一些特有的方法与限制

另一种更显式的写法

var py2: Tuple2[Int, String] = (40, "")

Tuple2 是类型,后面的数字是数组的元素数量,Tuple2 大致相当于 Object[2]

访问元素

可以用下标取值

    var py2: Tuple2[Int, String] = (40, "str")
    
    println(py2._1)
    println(py2._2)
解构
    var py2: Tuple2[Int, String] = (40, "str");
    
    var (v1, v2) = py2;
    
    println(v1);
    println(v2);
模式匹配(case when)
    val planetDistanceFromSun = List(("Mercury", 57.9), ("Venus", 108.2), ("Earth", 149.6), ("Mars", 227.9), ("Jupiter", 778.3))

    planetDistanceFromSun.foreach { tuple =>
      {
        tuple match {
          case ("Mercury", distance) => println(s"Mercury is $distance millions km far from Sun")
          case p if (p._1 == "Venus") => println(s"Venus is ${p._2} millions km far from Sun")
          case p if (p._1 == "Earth") => println(s"Blue planet is ${p._2} millions km far from Sun")
          case _ => println("Too far....")
        }
      }
    }
for中的使用
val numPairs = List((2, 5), (3, -7), (20, 56))

for ((a, b) <- numPairs) {
  println(a * b)
}
函数变量
val addOne = (x: Int) => x + 1
println(addOne(1)) // 2
方法
def add(x: Int, y: Int): Int = x + y
println(add(1, 2)) // 3

与函数不同,方法中可以做更多事情

      def add(x: Int, y: Int): Int = {
        var nv = 9; 
        return x + y + nv
      }
      println(add(1, 2)) // 12

甚至多个参数列表

      def addThenMultiply(x: Int, y: Int)(multiplier: Int): Int = (x + y) * multiplier
      println(addThenMultiply(1, 2)(3)) // 9

访问修饰符

private,protected,public。缺省为public
与java不同的地方

private

private,更严格,只在内部可见。也即外部类中不可见,虽然也没人那么用就是了。用java代码来表示就是类似下面这样的代码将变得非法

public class Test02 {

	public static void main(String[] args) {
		int w = new Test02().new Inner().i;
	}
	
	class Inner{
		private int i = 1;
	}
	
}

用scala代码来表示

class Outer{
    class Inner{
    private def f(){println("f")}
    class InnerMost{
        f() // 正确
        }
    }
    (new Inner).f() //错误
}
protected

比java更严格,只有当前类,子类可访问

循环

for

查了不少资料,确实有很多种写法,但是本质上都只是foreach,这东西没什么灵活性,随便记几个例子好了。

    for (i <- 1 to 3) {
      println(i)
    }

普通for循环

case class User(name: String, age: Int)

val userBase = List(User("Travis", 28),
  User("Kelly", 33),
  User("Jennifer", 44),
  User("Dennis", 23))

val twentySomethings = for (user <- userBase if (user.age >=20 && user.age < 30))
  yield user.name  // i.e. add this to a list

twentySomethings.foreach(name => println(name))  // prints Travis Dennis

循环里面加了个判断,并且用了yield关键字——scala的for循环可以通过yield使用返回值

while

与java中的一致

        var i : Int= 0;
        while(i < 3){
          println(i)
          i+=1;
        }
循环控制

scala中不直接提供break、continue语法,需要额外加一些东西

import util.control.Breaks._

object Test01 {
  def main(args: Array[String]): Unit = {
    //foreach break
    breakable{
      for (i <- 1 to 10) {
        println(i)
        if (i == 3)
          break;
      }}
    //foreach continue
    for (i <- 1 to 10) {
      breakable {
        if (i == 3)
          break
        println(i)
      }
    }
    //while break
    breakable{
      var i : Int = 0;
      while (i < 10) {
        println(i);
        if(i == 1)
          break;
      }}
    //while continue
    var i : Int = 0;
    while (i < 10){
      breakable{
        println(i);
        if(i == 1)
          break;
      }
    }
    
  }
}
嵌套循环控制

大致相当于java中的这种语法

		//java
		a: for(int i = 0; i < 3; i++){
			break a;
		}
import util.control.Breaks._
import scala.util.control._

object Test01 {
   def main(args: Array[String]) {
      var a = 0;
      var b = 0;
      val numList1 = List(1,2,3,4,5);
      val numList2 = List(11,12,13);

      val outer = new Breaks;
      val inner = new Breaks;

      outer.breakable {
         for( a <- numList1){
            println( "Value of a: " + a );
            inner.breakable {
               for( b <- numList2){
                  println( "Value of b: " + b );
                  if( b == 12 ){
                     inner.break;	//内层break
                     //outer.break;	//直接跳出外层
                  }
               }
            } // 内嵌循环中断
         }
      } // 外部循环中断
   }
}

方法与函数

  • Scala 有方法与函数,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。
  • Scala 中的方法跟 Java 的类似,方法是组成类的一部分。
  • Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象。
  • Scala 中使用 val 语句可以定义函数,def 语句定义方法。

这段来自菜鸟教程的话可以带来一个直观的认识——方法与函数基本可以看做一种东西的两种写法。

A Function Type is (roughly) a type of the form (T1, …, Tn) => U, which is a shorthand for the trait FunctionN in the standard library. Anonymous Functions and Method Values have function types, and function types can be used as part of value, variable and function declarations and definitions. In fact, it can be part of a method type.

A Method Type is a non-value type. That means there is no value - no object, no instance - with a method type. As mentioned above, a Method Value actually has a Function Type. A method type is a def declaration - everything about a def except its body.

虽然有许多不同,不过把方法当做java的方法来用,函数当做js的函数来用大概就可以了的感觉。

方法

定义:

def functionName ([参数列表]) : [return type] = {
   function body
   return [expr]
}

需要注意一下的是方法里面甚至可以再写一个方法(允许嵌套方法)

方法可以接受多个参数列表

def addThenMultiply(x: Int, y: Int)(multiplier: Int): Int = (x + y) * multiplier
println(addThenMultiply(1, 2)(3)) // 9
方法的返回值

: [return type] 定义返回值类型,Unit相当于java中的void,不过即使定义了Unit,也依然可以使用return语句或者使用输出语句将方法打印,不过输出结果都是(),一个空的元组。

object Test02 {
  def main(args: Array[String]): Unit = {
    println(mhd() == ());  //true
  }
  
  def mhd() : Unit = {
    return 123;
  }
}

方法中允许省略return关键字,并将最后一行的结果自动识别为返回值。
不过怎么想都是个鸡肋的特性,先不说不少方法都需要多个return来控制逻辑,return这个关键字本身也会有一个提示的作用,帮助更快的理解代码。

函数

函数的一般写法

    ((x: Int) => x + 1);              //定义匿名函数
    ((x: Int) => println(x))(1);      //调用匿名函数  
    println(((x: Int) => x + 1)(1));  //调用匿名函数并输出返回值
    
    var aa = (x: Int, y: Int) => x + y + 1;  //定义多个参数
    
    (x: Int, y: Int) => {
      var z = x + y;
      z + 1;
    };   // 使用块来调用多行代码
高阶函数

higher-order function,就是把函数当变量用,可以作为参数,也可以作为返回值。

  • 函数作为参数
    var fc = (f : Int => String) => f(1);
    println(fc((x) => "" + x));

解释:上面代码中的Int为型参f函数在fc函数中的参数类型,String为f的返回类型。

如果f有多个参数,可以这样写

    var fc = (f : (Int, Int) => String) => f(1, 2);
    println(fc((x, y) => "" + x + y));
  • 将函数作为返回值的函数
    var ff = () => {(a : Int, b : Int) => {a + b}};
    
    var backFunc = ff();
    println(backFunc(1, 2));

提示:(a : Int, b : Int) => {a + b} 是函数ff所返回的匿名函数

与java的整合

scala作为在jvm上执行的语言,基本可以直接调用java代码,但是在一些细节上还是有一些差距,需要记录一下。

网上没找到相关资料,想到一个记一个。


scala会默认引用引用java.lang.*中的,这一点与java一致。若引用别的包,需要手动import。scala对import进行了一定程度的扩展,但是也是完全兼容java语法的。

scala中使用java.util.ArrayList

scala肯定是由自己的集合实现的(https://www.scala-lang.org/api/current/scala/collection/immutable/List.html),但是也可以直接使用java中的类。

import java.util.ArrayList

object Test02 {
  
  def main(args: Array[String]): Unit = {
    
    var list = new ArrayList
    println(list.size());
    
  }
}

这里list应该是不能直接添加值的

    var list = new ArrayList;
    list.add("");

这么写会报错,需要指定泛型

    var list = new ArrayList[String];
    list.add("");

java与scala对象互相转换

集合
    import scala.collection.JavaConverters._

    val list: java.util.List[Int] = List(1, 2, 3, 4).asJava
    list.size();    //java object
    
    val buffer: scala.collection.mutable.Buffer[Int] = list.asScala
    buffer.length;  //scala object

简单来说,需要先引入import scala.collection.JavaConverters._

具体规则在官方文档中有详细说明
https://www.scala-lang.org/api/current/scala/collection/JavaConverters$.html
抄过来一点
The following conversions are supported via asScala and asJava:

scala.collection.Iterable       <=> java.lang.Iterable
scala.collection.Iterator       <=> java.util.Iterator
scala.collection.mutable.Buffer <=> java.util.List
scala.collection.mutable.Set    <=> java.util.Set
scala.collection.mutable.Map    <=> java.util.Map
scala.collection.concurrent.Map <=> java.util.concurrent.ConcurrentMap

The following conversions are supported via asScala and through specially-named extension methods to convert to Java collections, as shown:

scala.collection.Iterable    <=> java.util.Collection   (via asJavaCollection)
scala.collection.Iterator    <=> java.util.Enumeration  (via asJavaEnumeration)
scala.collection.mutable.Map <=> java.util.Dictionary   (via asJavaDictionary)

In addition, the following one-way conversions are provided via asJava:

scala.collection.Seq         => java.util.List
scala.collection.mutable.Seq => java.util.List
scala.collection.Set         => java.util.Set
scala.collection.Map         => java.util.Map

The following one way conversion is provided via asScala:

java.util.Properties => scala.collection.mutable.Map

In all cases, converting from a source type to a target type and back again will return the original source object. For example:

import scala.collection.JavaConverters._

val source = new scala.collection.mutable.ListBuffer[Int]
val target: java.util.List[Int] = source.asJava
val other: scala.collection.mutable.Buffer[Int] = target.asScala
assert(source eq other)

Alternatively, the conversion methods have descriptive names and can be invoked explicitly.

scala> val vs = java.util.Arrays.asList("hi", "bye")
vs: java.util.List[String] = [hi, bye]

scala> val ss = asScalaIterator(vs.iterator)
ss: Iterator[String] = <iterator>

scala> .toList
res0: List[String] = List(hi, bye)

scala> val ss = asScalaBuffer(vs)
ss: scala.collection.mutable.Buffer[String] = Buffer(hi, bye)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值