Scala基本语法及使用

Scalahtml

Author: Lijbjava

Email: lijb1121@163.comes6

Scala是一门多范式的编程语言,同时支持面向对象和面向函数编程风格。它以一种优雅的方式解决现实问题。虽然它是强静态类型的编程语言,可是它强大的类型推断能力,使其看起来就像是一个动态编程语言同样。Scala语言最终会被翻译成java字节码文件,能够无缝的和JVM进行集成,同时可使用Scala调用java的代码库。express

编程指南:https://docs.scala-lang.org/tour/tour-of-scala.html编程

Scala环境搭建数组

下载scala:https://www.scala-lang.org/download/2.11.12.htmlapp

Windows版本安装dom

  • 点击scala-2.11.12.msi傻瓜安装编程语言

  • 配置Scala的环境变量SCALA_HOME变量ide

    SCALA_HOME=C:\Program Files (x86)\scala PATH=%SCALA_HOME%/bin

  • 打开命名窗口

    C:\Users\HIAPAD>scala Welcome to Scala 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_161). Type in expressions for evaluation. Or try :help.

    scala>

CentOS安装

  • 下载scala-2.11.12.rpm

  • 安装配置Scala

    [root@CentOS ~]# rpm -ivh scala-2.11.12.rpm Preparing... ########################################### [100%] 1:scala ########################################### [100%] [root@CentOS ~]# scala Welcome to Scala 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_171). Type in expressions for evaluation. Or try :help.

IDEA集成Scala开发环境

  • 在File>Setting>Plugins点击install plugin from disk选项,选择scala-intellij-bin-2018.2.11.zip安装成功后,重启IDEA

Scala变量

参考:https://docs.scala-lang.org/resources/images/tour/unified-types-diagram.svg

scala> var i=1
i: Int = 1
scala> var i="abc"
i: String = abc
scala> var i: ="abc"
<console>:11: error: type mismatch;
 found   : String("abc")
 required: Int
       var i:Int="abc"
                 ^

Scala全部的变量在声明时能够省略类型,由编译器自动推断,一旦编译后,类型固定,不能够更改

scala> var i=1
i: Int = 1

scala> i="abc"
<console>:12: error: type mismatch;
 found   : String("abc")
 required: Int
       i="abc"
         ^
scala> var i:Int=1:Int
i: Int = 1

var和val区别?

var修饰的变量值是能够改变的

val修饰的值,不能够改变相似于java中final

scala> val i=10
i: Int = 10

scala> i=1000
<console>:12: error: reassignment to val
       i=1000
        ^

字面值类型相互转换

scala> val face: Char = '☺'
face: Char = ☺

scala>     val i:Int =face
i: Int = 9786

scala>     val c:Char = i.toChar
c: Char = ☺

变量定义

var|val 变量名[:变量类型]=变量值[:变量类型]
var|val 变量名 = 变量值 //使用Scala的类型推断
var a:Int = 1
var str:String = "hello world"
var pair:(Int,String) = (1,"测试") //元组
var b=1
var i:Int=1
var j=1:Byte
var tuple=(1,2)//元组

元组在Scala中是由多种类型的变量组装而成,一旦赋值,不可更改

scala> var pair:(String,Int)= "zhangsan" -> 10
pair: (String, Int) = (zhangsan,10)

scala> var pair:(String,Int)= ("zhangsan", 10)
pair: (String, Int) = (zhangsan,10)

scala> var pair= ("zhangsan", 10)
pair: (String, Int) = (zhangsan,10)

scala> var pair= "zhangsan" -> 10
pair: (String, Int) = (zhangsan,10)

scala> var tuple:(Int,Int,String)=(1,2,"Hello")
scala> tuple._1
res4: Int = 1

scala> tuple._2
res5: Int = 2

scala> tuple._3
res6: String = Hello

scala> tuple._3="world"
<console>:12: error: reassignment to val
       tuple._3="world"
               ^

算术运算符

算术运算符:+、-、*、/、%、

关系运算符:==、!=、>、<、>=、<=

逻辑运算符:&&、||、!

位运算符:&(按位与)、|(按位或)、^(异或)、~(取反)、<<、>>、>>>(无符号)

赋值运算符:= 、

组合赋值:(算术|位运算=)

判断Scala的类型

var i=0
var sex:Any={
    if(i>0){
        true
    }else{
        "不知道"
    }
}
if(sex.isInstanceOf[Boolean]){
    println("你是布尔")
}else{
    println("你是String:"+sex.asInstanceOf[String])
}

Scala的分支语句

if条件分支

if(布尔表达式 1){  
  // 若是布尔表达式 1 为 true 则执行该语句块 
}else if(布尔表达式 2){
  // 若是布尔表达式 2 为 true 则执行该语句块 
}else if(布尔表达式 3){ 
  // 若是布尔表达式 3 为 true 则执行该语句块 
}else {
  // 若是以上条件都为 false 执行该语句块
}

while循环控制

//求1到100的和
    var i=0 //可省略
    var n=0 //可省略
    while(i< 100){
        i+=1
        n+=i
    }
    print("while循环后结果为:"+n)

do-while循环

//求1到100的和
    var i=0 //可省略
    var n=0 //可省略
    do{
       i+=1
       n+=i
    }while(i<100)
    print("do->while循环后结果为:"+n)

for循环

//求1到100的和
    var i=0 //可省略
    var n=0 //可省略
    for(i<-1 to 100 by 2){
      n+=i
    }
    println(n)

for 循环 中你可使用分号 (;) 来设置多个区间,它将迭代给定区间全部的可能值(实现嵌套)

//100之内能被3整除不能被5整除的和
     var i=1
     var result=0 //可省略
     for(i<-1 to 100 if i%3==0 && i%5!=0){
       result+=i
     }
     print(result)
  • for循环集合

    val list = List(1,2,3,4,5,6)
     for (a<-list){
       println(a)
     }
  • for循环过滤

    //例一:百钱买百鸡
      var x = 0 //可省略
      var y = 0 //可省略
      for (x <- 0 to 33) {
        var maxy = (100 - x * 3) / 2
        for (y <- 0 to maxy) {
          var z = 100 - x - y;
          if (3 * x + 2 * y + z / 3.0 == 100 && x + y + z == 100) {
            println("公鸡:" + x + "只;" + "母鸡:" + y + "只;" + "小鸡:" + z + "只。");
          }
        }
      }
    
      //例二:
      var a = 0; //可省略
      val list = List(1,2,3,4,5,6,7,8,9,10);
      for(a<-list
        if a%2==0;if a<=4){
       	 println(a)
      }
  • for使用 yield

    //yied至关于提取出 var a = 0; val numList = List(1,2,3,4,5,6,7,8,9,10); // for 循环 var retVal = for{ a <- numList     if a != 3; if a < 8             }yield a // 输出返回值 for( a <- retVal){ println( "Value of a: " + a );、 }

match-case

Scala中取消了switch-case语法,取而代之的是使用match-case语法,也称为模式匹配。

var sex="..."
    var alias =sex match {
      case "boy" => "男孩"
      case "girl" => "女孩"
      case default => "怪物"
    }
    println(alias)

default能够用_替换

Break语法 Scala 语言中默认是没有 break 语句,可是你在 Scala 2.8 版本后可使用另一种方式来实现 break 语句。当在循环中使用 break 语句,在执行到该语句时,就会中断循环并执行循环体以后的代码块。Scala 中 break 的语法有点不大同样,格式以下:

var a = 0;
    val numList = List(1,2,3,4,5,6,7,8,9,10);
    val break = new  Breaks
    break.breakable(
      for (a<-numList){
        println( "Value of a: " + a )
        if(a==4){
          break.break()
        }
      }
    )
    println( "After the loop" );

Scala函数

函数声明

def functionName ([参数列表]) : [return type]

标准函数

def sum(x:Int,y:Int):Int={
  return x+y } //能够尝试省略返回值类型 
def multi(x:Int,y:Int)={
  x*y 
} 
def sayHi(name:String):Unit={
  println("hi~ "+name) 
}

指定函数名

def main(args: Array[String]): Unit = {
  println(sum(5,2))
}
def sum (x:Int,y: Int): Int ={
  return x+y
}

可变长参数函数

要求必须放置在因此参数的最后

def main(args: Array[String]): Unit = {
    println(sum(1,2,3,4,5,6,7,8,9,10))//结果:55
}
def sum(args: Int*): Int = {
  var result = 0
  for (i <- args) {
    result += i
  }
  return result
 }
//打印参数WrappedArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)  说明传入的参数是个一个args数组

默认参数值

def main(args: Array[String]) {
  sayHi("ww")       
  sayHi() 
} 
def sayHi(name:String="zhangsan"):Unit={ 
  println("hi~ "+name) 
}

内嵌函数

def main(args: Array[String]): Unit = {
    println(factorial(5))
}
def factorial (x:Int)={
  def mulit(i:Int):Int={
    if(i>0){
      i*mulit(i-1)
    }else{
      1
    }
  }
  mulit(x)
}

匿名函数

匿名函数 Scala 中定义匿名函数的语法很简单,箭头左边是参数列表,右边是函数体。使用匿名函数后,咱们的代 码变得更简洁了。本质是一个lambdar表达式

(x:Int,y:Int) => {x+y}

将一个函数变成变量

//函数
def fun(x:Int):Int={
    return x+1
}
//改写成变量
var f1:(Int)=>Int=(x)=>x+1
val f2 = (x: Int) => x + 1

函数的返回值问题

1,声明函数的返回值类型,则在函数返回时必定要符合返回类型

2,能够不声明函数返回值类型,scala解释器会自动推断返回的数据类型

3,递归函数必须显式声明返回的类型

4,定义函数时没有等号= 则没有返回值。这类函数至关于一个执行过程

高阶函数

在数学和计算机科学中,高阶函数是至少知足下列一个条件的函数

  • 接受一个或多个函数做为输入
  • 输出一个函数

在数学中它们也叫作算子(运算符)或泛函。微积分中的导数就是常见的例子,由于它映射一个函数到另外一个函数。

//求给定区间的整数和
def main(args: Array[String]): Unit = {
    println(sumInts(2,5))
}
def sumInts(a: Int, b: Int): Int =
    if(a > b) 0 else a + sumInts(a + 1, b)
}

//求给定区间连续的整数的平方和
def main(args: Array[String]): Unit = {
    println(sumSquare(1,100))//结果为338350
}
def square(x: Int) = x * x
def sumSquare(a:Int,b:Int):Int={
  if(a > b) 0 else square(a)+sumSquare(a+1,b)
}

map方法将一个函数应用到某个集合的全部元素并返回结果;foreach将函数应用到每一个元素。

(1 to 9).map("^" * _).foreach(println _)
^^
^^^
^^^^
^^^^^
^^^^^^
^^^^^^^
^^^^^^^^
^^^^^^^^^

filter方法输出全部匹配某个特定条件的元素:

(1 to 9).filter(_ % 2 == 0).foreach(println _)
//结果:2 4 6 8

函数柯里化(Currying)

柯里化(Currying)指的是将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数为参数的函数。

  • 返回函数的函数

在上面高阶函数的例子中,咱们经过def sumInts(a: Int, b: Int): Int = sum(x => x, a, b)、def sumSquared(a: Int, b: Int): Int = sum(x => x*x, a, b)来定义新的函数,上面这两个函数每次都要传入a和b两个参数到sum函数中,咱们可否简化这些参数使得函数定义更简单呢?

咱们能够经过返回函数的函数来简化参数:

/*当你调用sum1(2)(8)时,其实是依次调用两个普通函数(非柯里化函数), 第一次调用使用一个参数x,返回一个函数类型的值,第二次使用参数y调用这个函数类型的值*/
def sum(f: Int => Int): (Int, Int) => Int = {
    def sumF(a: Int, b: Int): Int = 
        if(a > b) 0
        else f(a) + sumF(a+1, b)
    sumF
}
//因而获得以下定义,这样就简化了参数
def sumInts = sum(x => x)
def sumSquared = sum(x => x * x)
def sumPowersOfTwo = sum(powerOfTwo)
  • 多个参数列表

根据上面的例子,咱们能不能更加简化,省去sumInts、sumSquared、sumPowersOfTwo这几个中间函数的形式呢?

经过sum(square)(1, 10)函数来替代sumSquared函数。

通常状况,这类函数的左结合的:sum(square)(1, 10) == (sum(square))(1, 10)。

咱们能够这样定义sum函数:

def sum(f: Int => Int)(a: Int, b: Int): Int = 
  if(a > b) 0 else f(a) + sum(f)(a + 1, b)

这使得函数编写更加简洁。

通常的,多参数函数定义为def f(args1)...(argsn) = E,

当n > 1时,等同于def f(args1)...(args n-1) = {def g(argsn) = E; g}或者def f(args1)...(args n-1) = (argsn => E)。

若是重复这个过程n次,获得def f = (args1 => (args2 => ... (argsn => E) ) )。

这种函数定义称为柯里化(Currying)。

类和object

Scala中的类是用于建立对象的蓝图,其中包含了方法、常量、变量、类型、对象、特质、类,这些统称为成员。因为Scala没有静态方法和静态类,经过object去定义静态方法或者静态对象。当object和Class放在一个文件中时候称该object为伴生对象。

object(单例类)

object UserService {
  def main(args: Array[String]): Unit = {
    var us1=UserService
    var us2=UserService
    println(us1==us2) //结果为true-->说明us1和us2是同一个对象-->单例
    UserService.sayHi()
    us1.sayHi()
    us2.sayHi()
    sayHi()
  }
  def sayHi():Unit={
    println("hello")
  }
}

类定义

class Student {
  var id=1
  var name="zhangsan"
  var age=18
  var birtDay=new Date()
}

构造器

在scala中只有Class或者abstract Class才能有构造方法,Scala中声明在Class上的构造必须为最简构造,其余构造方法参数必须涵盖最简构造。

class User{
  var id:Int = _
  var name:String = _
  def this(id:Int,name:String){
   this()
   this.id=id
   this.name=name
  }
  def sayHi(): Unit ={
    println(id+" "+name)
  }
}
-----
class User(var id:Int,var name:String){
  def this(){
    this(1,"张三")
  }
  def sayHi(): Unit ={
    println(id+" "+name)
  }
}

伴生对象

当类名和单例类名字同样的时候,咱们把单例类称为伴生对象

class User{ }
object User {
  def main(args: Array[String]): Unit = {
    var u1=User
    var u2=User
    var u3=new User()
    println(u1==u2)//true
    println(u1==u3)//false
  }
}

apply&unapply

Scala中的 apply 方法有着不一样的含义, 对于函数来讲该方法意味着调用function自己, 如下说明摘自

Programming in Scala, 3rd Edition

Every function value is an instance of some class that extends one of several FunctionN traits in package scala, such as Function0 for functions with no parameters, Function1 for functions with one parameter, and so on. Each FunctionN trait has an apply method used to invoke the function.

在Scala语言中, 函数也是对象, 每个对象都是scala.FunctionN(0-22)的实例, 其中N是函数参数的数量, 例如咱们定义一个函数并赋值给一个变量:

def main(args: Array[String]): Unit = {
    println(fun(2)) //结果为2
    var fun1:(Int)=>Int=(x)=>x+1
    val fun2 = (x: Int) => x + 1
    println(fun1.apply(2)) //结果为2
    println(fun2.apply(2)) //结果为2
  }
def fun(x:Int):Int={
  return x+1
}

apply 方法用在object中通常做为工厂方法用于产生Class对象,一般,在一个类的半生对象中定义apply方法,在生成这个类的对象时,就省去了new关键字。

class Student (name:String) { }
object Student{
  def apply(name: String): Student = new Student(name)
  def main(args: Array[String]): Unit = {
    var s1=new Student("张三")
    var s2= Student("李四")
    var s3=Student("李四")
    println(s1) //com.baizhi.zpark.Student@47f37ef1
    println(s2) //com.baizhi.zpark.Student@5a01ccaa
    println(s3) //com.baizhi.zpark.Student@71c7db30
    println(s1==s2) //false
    println(s2==s3) //false
  }
}

extractor object是具备unapply方法的对object。unapply方法能够看作是apply方法的相反操做,apply方法接受构造参数变成对象,而unapply方法接受一个对象,从中提取值。

object CustomerID {
  def apply(name: String) = s"$name--${Random.nextLong}"
  def unapply(customerID: String): Option[String] = {
    val stringArray: Array[String] = customerID.split("--")
    if (stringArray.tail.nonEmpty) Some(stringArray.head) else None
  }
}

val customer2ID = CustomerID("Nico")
val CustomerID(name) = customer2ID
println(name)  // prints Nico

extractor object 更多可参考 https://docs.scala-lang.org/tour/extractor-objects.html

抽象类/抽象方法

//抽象方法
abstract class Animal(name:String) {
  def eat():Unit={
    println("animal can eat...")
  }
  def  sleep():String
}
//集成抽象类--覆盖里面的抽象方法
object AnimalImpl extends Animal {
  override def sleep(): Unit = {
    println("Animal sleeping 5 hours")
  }
  def main(args: Array[String]): Unit = {
    sleep() //调用覆盖的方法
    eat()   //调用继承的抽象类中的非抽象方法
  }
}

特质trait(java中的接口)

trait Speakable {
    def speek():Unit
}
trait Flyable{
   def fly():Unit
}

继承&实现

  • 类-类、类接口

    class Dog(name:String) extends Animal(name:String) with Speakable { override def sleep(): String = { "i'm a dog I sleep 8 hours" } override def speek(): Unit = { println("wang wang ~~") } override def eat(): Unit = { println("啃骨头") } } object Dog{ def apply(name: String): Dog = new Dog(name) def main(args: Array[String]): Unit = { var dog=Dog("小花") dog.eat() } } class Bird extends Flyable with Speakable { override def fly(): Unit = { println("i can fly") } override def speek(): Unit = { println("唧唧咋咋") } } object Bird{ def apply(): Bird = new Bird() def main(args: Array[String]): Unit = { var bird=Bird() bird.fly() } }

  • 接口-接口

    trait A{} trait C{} trait B extends A with C{}

接口动态植入

class Bird extends Flyable {//Flyable是trait
  override def fly(): Unit = {
    println("i can fly")
  }
}
object Bird{
  def main(args: Array[String]): Unit = {
    var bird=new Bird() with Speakable {
      override def speek(): Unit = {
        println("唧唧咋咋")
      }
    }
    bird.speek()
  }
}

注意在覆盖有实现的方法必须添加overwrite一个类只能继承一个类with多个trait例如

Class A extends B with C with D{ }

上述的B多是特质也能够是抽象类 但C、D必须是特质。

this&self-type

和java有所不一样在Scala中class和object均可以使用this关键字表明自身。同时Scala支持给当前对象起别名

class Student(name:String) {
    self =>  //起别名  用self表明当前对象
    def sayHello(): Unit ={
      println(this == self)
      println("hello "+self.name)
    }
}
object Student{
  def apply(name: String): Student = new Student(name)
  def main(args: Array[String]): Unit = {
     var stu=Student("zhangsan")
    stu.sayHello()
  }
}

self-type是一种声明Trait必须混合到另外一个Trait的方法,即便它没有直接扩展它。这使得依赖的成员能够在没有导入的状况下使用。

定义:特质能够要求混入它的类扩展自另外一个类型,可是当使用自身类型(self type)的声明来定义特质时(this: ClassName =>),这样的特质只能被混入给定类型的子类当中。 若是尝试将该特质混入不符合自身类型所要求的类时,就会报错。

从技术角度上看,自身类型是在类中提到this时,对于this的假设性类型。

从实用角度上看,自身类型指定了对于特质可以混入的具体类的需求。若是你的特质仅用于混入另外一个或几个特质,那么能够指定那些假设性的特质。

trait User {
  def username: String
}
trait Tweeter {
  this: User =>  // reassign this
  def tweet(tweetText: String) = println(s"$username: $tweetText")
}

class VerifiedTweeter(val username_ : String) extends Tweeter with User {  // We mixin User because Tweeter required it
 def username = s"real $username_"
}

val realBeyonce = new VerifiedTweeter("Beyoncé")
realBeyonce.tweet("Just spilled my glass of lemonade")

可见性控制

Scale和java类型能够控制Scala中对象的可见性,例以下面表示建立一个公开类,任何包下的类均可以使用,同时该类下的成员变量都是公开。

class Student {
  var id=1
  var name="zhangsan"
  var age=18
  var birtDay=new Date()
}
  • private限定 private修饰的属性只能对本类可使用,对于伴生对象可见 private修饰类,可继承而且继承以后能够访问父类属性和方法,除非父类的属性和方法加上private修饰符以后不可访问

    class Student { private var id=1 var name="zhangsan" var age=18 var birtDay=new Date() } object Student{ def apply(): Student = new Student() def main(args: Array[String]): Unit = { val student = Student() student.id } }

  • protected限定 protected修饰的属性对本类/伴生对象可用,对于子类/子类的伴生对象可见

    class Student { protected var id=1 var name="zhangsan" var age=18 var birtDay=new Date() } object Student{ def apply(): Student = new Student() } class SmallStudent extends Student{ } object SmallStudent { def apply(): SmallStudent = new SmallStudent() def main(args: Array[String]): Unit = { val student = SmallStudent() student.id } }

  • this限定 若是严格限定属性能够操做范围仅仅限制在本类,去除伴生对象的可见性,能够添加this限定

    class Student { protected|private[this] var id=1 var name="zhangsan" var age=18 var birtDay=new Date() } object Student{ def apply(): Student = new Student() }

  • 包限定 Scala还能够作包限定,表示id属性对Student的子类可见,其余类必须是同包下可见

    package com.jiangzz.demo import java.util.Date class Student { protected[demo] var id=1 var name="zhangsan" var age=18 var birtDay=new Date() } object Student{ def apply(): Student = new Student() }

  • final限定

final能够修饰Class和方法,final修饰的类不能够被继承,修饰的方法不能够被覆盖,可是final修饰属性时没有效果,val修饰属性才时不可变的。

final class Student(name:String) {
  final def sayHi(name:String):String={
    "hello "+name
  }
}
  • 方法覆盖&重载 scala保留了java中的方法重载和覆盖功能具体使用和Java语法相似。

    def fun(x:Int,y:Int):Int={ x+y } def fun(x:String,y:Int):String={ x+y } override def toString: String = { "..." }

函数对象(重点)

Partial Applied Function(部分应用函数)

函数对象这是一种特殊的对象,也有人称之为高阶函数。咱们把不具备任何可改变状态的对象称为函数式对象。对于函数而言分为参数类型和函数体实现,Scala的函数对象就是一种特殊的class既能够担当函数计算职责又能够做为变量传递。Scala能够很方便的将函数转变成为函数对象。

scala>  def sum(v1:Int,v2:Int):Int={
     |     return v1+v2
     |   }
sum: (v1: Int, v2: Int)Int

scala> val s1=sum(_:Int,1)
s1: Int => Int = $$Lambda$1291/1237850567@17d28c1d

scala> s1(3)
res12: Int = 4

scala> val s2=sum _
s2: (Int, Int) => Int = $$Lambda$1158/879220032@67710b92

函数对象

一般将s1和s2称为sum函数的部分应用函数(Partial Applied Function),仔细观察能够发现当sum转变为s一、s2对于Scala而言都是某种对象类型的变量。

对于s1而s1的类型就是Int=>Int类型变量;s2而言该s2的类型就是(Int,Int)=>Int类型。对于Scala而言Scala在作方法解析的时候底层会将方法转换为Function1~22对象类型,当程序编写一个方法事实上是在建立Function[1~22]对象,调用对象的方法就等价于调用Function的apply方法

scala>  def sum(v1:Int,v2:Int):Int={
     |     return v1+v2
     |   }
sum: (v1: Int, v2: Int)Int

scala> val s=sum _
s: (Int, Int) => Int = $$Lambda$1295/814452367@1faa627c
    scala> s.isInstanceOf[Function2[Int,Int,Int]]
res20: Boolean = true

scala> s.isInstanceOf[(Int,Int)=>Int]
res21: Boolean = true
scala> s.apply(1,2)
res0: Int = 3

以上代码等价于

scala> val s=new Function2[Int,Int,Int] {
     |       override def apply(v1: Int, v2: Int): Int = {
     |         return v1+v2
     |       }
     |     }
s: (Int, Int) => Int = <function2>

scala>     s.apply(1,2)
res11: Int = 3

经过函数到对象的转换,咱们不难发现,能够将任意一个函数类型转换为变量类型,函数转换对象类型的变量转换规则以下:

按照上述转换规则 将函数声明转换为变量类型,将函数实现用lambda表达式实现就能够实现将函数转变Function类型的变量。

class SumFunction extends ((Int,Int)=>Int){
  override def apply(v1: Int, v2: Int): Int = {
    return v1 + v2
  }
}
object SumFunction{
  def main(args: Array[String]): Unit = {
      val s=new SumFunction()
      println(s.apply(1,2))
      println(s.isInstanceOf[Function2[Int,Int,Int]])
      println(s.isInstanceOf[(Int,Int)=>Int])
  }
}

使用场景以下

class Student(val name:String) {
  def map(f:Student=>String):String={
    return f(this)
  }
}
object Student{
  def apply(name: String): Student = new Student(name)
  def main(args: Array[String]): Unit = {
     val stu=Student("张三")
     var str=stu.map(x=>x.name)
     println(str)
  }
}

分析:

复杂的函数对象编程

class Student(val name:String) {
  def map1(f:Student=>String):String={
    return f(this)
  }
  val map2:(Student => String) => String = (x:(Student=>String))=> x.apply(this)
}
object Student{
  def apply(name: String): Student = new Student(name)
  def main(args: Array[String]): Unit = {
    var s:Student=Student("王五")
    s.map1(x=>x.name)
    s.map2(x=>x.name)
  }
}

PartitalFunction(偏函数) -了解

偏函数主要适用于处理指定类型的据,一般用于集合处理中。

def main(args: Array[String]): Unit = {
    Array(1,2,3,"a","b","c").collect(pf1).foreach(println)
}
//自定义偏函数
val pf1 = new PartialFunction[Any, Int] {
  override def isDefinedAt(x: Any): Boolean = {
      if(x.isInstanceOf[Int]) true else false
  }
  override def apply(v1: Any): Int = {
      v1.asInstanceOf[Int]
  }
}
//case 实现偏函数
val pf2 :PartialFunction[Any, Int]={
  case x:Int => x+1
}

参考:https://blog.csdn.net/bluishglc/article/details/50995939

高阶函数

--->【摘自官方文档】

高阶函数将其余函数做为参数或做为结果返回函数。这是可能的,由于函数是Scala中的第一类值。这个术语在这一点上可能会有点混乱,咱们对于将函数做为参数或返回函数的方法和函数使用短语“高阶函数”。

其中一个最多见的例子是mapScala中可用于集合的高阶函数。

val salaries = Seq(20000, 70000, 40000)
val doubleSalary = (x: Int) => x * 2
val newSalaries = salaries.map(doubleSalary) // List(40000, 140000, 80000)

doubleSalary是一个函数,它接受一个Int x,并返回x * 2。一般,箭头左侧的元组=>是参数列表,右侧表达式的值是返回的值。在第3行,该函数doubleSalary应用于工资列表中的每一个元素。

要缩小代码,咱们可使函数匿名并将其做为参数直接传递给map:

val salaries = Seq(20000, 70000, 40000)
val newSalaries = salaries.map(x => x * 2) // List(40000, 140000, 80000)

注意x在上面的例子中如何不声明为Int。那是由于编译器能够根据函数映射的类型推断出类型。编写同一段代码的更为惯用的方法是:

val salaries = Seq(20000, 70000, 40000)
val newSalaries = salaries.map(_ * 2)

因为Scala编译器已经知道参数的类型(单个Int),所以您只须要提供函数的右侧。惟一须要注意的是,您须要使用_代替参数名称(它x在前面的示例中)。

  • 将方法强制转换为函数

也能够将方法做为参数传递给高阶函数,由于Scala编译器会将该方法强制转换为函数。

case class WeeklyWeatherForecast(temperatures: Seq[Double]) {

  private def convertCtoF(temp: Double) = temp * 1.8 + 32

  def forecastInFahrenheit: Seq[Double] = temperatures.map(convertCtoF) // <-- passing the method convertCtoF
}

这里将方法convertCtoF传递给forecastInFahrenheit。这是可能的,由于编译器强制convertCtoF执行该函数x => convertCtoF(x)(注意:x将是一个生成的名称,保证在其范围内是惟一的)。

  • 接受函数的函数

使用高阶函数的一个缘由是减小冗余代码。假设您想要一些能够经过各类因素提升某人工资的方法。若是不建立高阶函数,它可能看起来像这样:

object SalaryRaiser {

  def smallPromotion(salaries: List[Double]): List[Double] =
    salaries.map(salary => salary * 1.1)

  def greatPromotion(salaries: List[Double]): List[Double] =
    salaries.map(salary => salary * math.log(salary))

  def hugePromotion(salaries: List[Double]): List[Double] =
    salaries.map(salary => salary * salary)
}

请注意三种方法中的每一种方法如何仅因乘法因子而异。为简化起见,您能够将重复的代码提取到更高阶的函数中,以下所示:

object SalaryRaiser {

  private def promotion(salaries: List[Double], promotionFunction: Double => Double): List[Double] =
    salaries.map(promotionFunction)

  def smallPromotion(salaries: List[Double]): List[Double] =
    promotion(salaries, salary => salary * 1.1)

  def bigPromotion(salaries: List[Double]): List[Double] =
    promotion(salaries, salary => salary * math.log(salary))

  def hugePromotion(salaries: List[Double]): List[Double] =
    promotion(salaries, salary => salary * salary)
}

新方法promotion采用工资加上类型函数Double => Double (即采用Double并返回Double的函数)并返回产品。

  • 返回函数的函数

在某些状况下,您要生成一个函数。这是一个返回函数的方法示例。

def urlBuilder(ssl: Boolean, domainName: String): (String, String) => String = {
  val schema = if (ssl) "https://" else "http://"
  (endpoint: String, query: String) => s"$schema$domainName/$endpoint?$query"
}
val domainName = "www.example.com"
def getURL = urlBuilder(ssl=true, domainName)
val endpoint = "users"
val query = "id=1"
val url = getURL(endpoint, query) // "https://www.example.com/users?id=1": String

注意urlBuilder的返回类型(String, String) => String。这意味着返回的匿名函数须要两个字符串并返回一个String。在这种状况下,返回的匿名函数是(endpoint: String, query: String) => s"https://www.example.com/$endpoint?$query"。

隐式传值\隐式转换

  • 隐式值获取

    scala> implicit val n=1 //声明隐式值 scala> val b=implicitly[Int] b: Int = 1

    def main(args: Array[String]): Unit = { implicit var str="张三" //声明隐式值 val b=implicitly[String] println(b+"你好") //结果:张三你好 }

使用implicitly[类型],必须保证当前上下文有且仅有一个隐式值类型,通常这种隐式值变量的声明写在object单例类或者伴生对象中。

  • 隐式注入值

要求参数之中只能有一个implicit类型匹配。

implicit val  s="您好"
def sayHi1(implicit msg:String):Unit={
  println(msg)
}
def sayHi2(name:String)(implicit msg:String):Unit={//柯利化写法,要求必须做为最后一个参数传入
  println(msg+" "+name)
}
def sayHi3(implicit name:String,msg:String):Unit={//标准函数写法,要求implict修饰的隐式值,必须放在第一位
     println(msg+" "+name)
}
sayHi1
sayHi2("张三")
sayHi2("李四")("早上好")
sayHi3(implicitly[String],"hello") //不常见

错误写法:

def sayHi4(msg:String,implicit name:String):Unit={
    println(msg+" "+name)
}
def sayHi4(implicit name:String)(msg:String):Unit={
    println(msg+" "+name)
}

若是是标准函数写法,要求implict修饰的隐式值,必须放在第一位

若是是柯利化写法,要求必须做为最后一个参数传入

  • 参数隐式转换

    def main(args: Array[String]): Unit = { implicit def str2stu(v:String):Student={ new Student(v) } sayHi2Stu("王五") } def sayHi2Stu(stu:Student):Unit={ println("学生:"+stu.name+" 你好!") }

  • 隐式方法增强

    class Student(val name:String) { def study():Unit={ println("学生:"+name+" 学习..") } } object UserImplicts{ implicit class StudentImplicts(stu:Student){//参数给个对象就能给该对象加上该对象不存在的方法 def playGame():Unit={ println("学生 "+stu.name+" 玩游戏") } } } object Student{ import UserImplicts._ def main(args: Array[String]): Unit = { val s=new Student("张三") s.study s.playGame } }

隐式增强,优先调用对象本身的方法,若是该调用对象自己没有方法,会尝试查找编译的上下文,看当前上下文中是否有对应的隐式增强方法。

Scala 泛型

<:上边界限定(居多)

trait Keeper[U <: Animal]{
  def keep(a:U);
}

表示Keeper的实现类只能饲养Animal以及Animal的子类

:下界限定

trait Keeper[U >: Dog]{
  def keep(a:U);
}

表示Keeper的实现类只能饲养Dog或者Dog的父类

<%视图限定

implicit def str2Stu(v:String):Student={
  new Student(v)
}
 def getStu[T <% Student](v:T): T ={
  return v
 }
 val stu=getStu("张三")

运行的时候尝试将T类型隐式转换为Student类型

T:A上下文绑定

必须知足A[T]隐式值

class Student[T]() {
  def map(t:T):String={
    t.toString +" world!"
  }
}
def main(args: Array[String]): Unit = {
   implicit var s=new Student[String]() //Student隐士值
   say[String]("hello")
  }
  def say[T:Student](t:T):Unit={	//[T:Student]:类型参数	(t:T)值参数
    var stu=implicitly[Student[T]]
    stu.map(t)
  }
 def f[A:ClassTag](n: Int):Array[A] = {
       return new Array[A](n)
 }

上下文中,必须含有Student[String]隐式值,能够有效防止缺失参数,例如ClassTag该标签系统已经为 A:ClassTag建立了ClassTag[A]的隐式转换,而该隐式转换时在建立Array数组必需要用的。因此在给数组指定泛型的时候须要加ClassTag

多重界定符

  • A和B为T上界

    def sayT <: A with B:Unit={ println(v) } trait A{} trait B{}

  • A和B为T下界

    def sayT >: A with B:Unit={ println(v) } trait A{} trait B{}

  • 同时拥有上界和下界,而且A为下界,B为上界,A为B的子类,顺序不能颠倒

    def sayT >: A <: B:Unit={ println(v) } trait A{} trait B{}

  • 视图界定,即同时可以知足隐式转换的A和隐式转换的B

    def sayT <% A <% B:Unit={ println(v) } trait A{} trait B{}

+A 协变

若是范型里存在继承关系,则继承关系也是能够有多态的,子类范型赋值给父类范型,协变。

class Covariant[+T](t:T){}
val cov = new Covariant[Dog](new Dog("小狗"))
val cov2:Covariant[Animal] = cov

-A 逆变

class Covariant[-T](t:T){}
val cov = new Covariant[Animal](new Animal("动物"))
val cov2:Covariant[Dog] = cov

A 不变

class Covariant[T](t:T){}
val cov = new Covariant[Animal](new Animal("动物"))
val cov2:Covariant[Animal] = cov

Scala数组|集合

Array

var arr1=Array(1,2,3,4,5) //第一种建立方式 默认调用Array的apply方法
var arr2=new Array[Int](5)//第二种建立方式 指定泛型
println(arr1.apply(1))
arr1.foreach(i=>println(i))//数组遍历

Range区间

scala> var range=new Range(1,10,2)
range: scala.collection.immutable.Range = inexact Range 1 until 10 by 2
scala> var range=Range(1,10 ,2)
range: scala.collection.immutable.Range = inexact Range 1 until 10 by 2
scala> var range=0 to 10 by 2
range: scala.collection.immutable.Range = Range 0 to 10 by 2
scala> var range=0 until 10 by 2
range: scala.collection.immutable.Range = Range 0 until 10 by 2

向量

scala> var vector=Vector(1,2,3)
vector: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)
scala> var vector=for(i<- 0  to 10 by 2;if(i>4)) yield i
vector: scala.collection.immutable.IndexedSeq[Int] = Vector( 6, 8, 10)

Iterator

只能够遍历一次

var it=Iterator(1,2,3,4,5,6)
it.foreach(x=>println(x)) //第一次遍历有结果
it.foreach(println)		 //第二次遍历没结果

List集合(不可变集合)

  • :: 该方法被称为cons,意为构造,向队列的头部追加数据,创造新的列表。用法为 x::list,其中x为加入到头部的元素,不管x是列表与否,它都只将成为新生成列表的第一个元素,也就是说新生成的列表长度为list的长度+1(btw, x::list等价于list.::(x))
  • :+和+: 二者的区别在于:+方法用于在尾部追加元素,+:方法用于在头部追加元素,和::很相似,可是::能够用于pattern match ,而+:则不行. 关于+:和:+,只要记住冒号永远靠近集合类型就OK了。
  • ++ 该方法用于链接两个集合,list1++list2
  • ::: 该方法只能用于链接两个List类型的集合

::/+:追加元素

var list =List(1,2,3,4,5)
list::=6			 //默认追加到集合的最前面
list+:=8			 //默认追加到集合的最前面
list.foreach(println) //6,1,2,3,4,5
list(0)=10 //报错 list不容许修改
println(list(0))  //获取第一个元素

:::合并集合

var list1=List(1,2,3)
var list2=List(4,5,6)
list1:::=list2
list1.foreach(println) //把list2合并追加到list1前面获得新的集合{4,5,6,1,2,3}
list2.foreach(println) //4,5,6 list2结果不变

drop

var list2=List(4,5,6,7,8)
val ints = list2.drop(2) //删除前两个元素返回一个新集合ints
ints.foreach(println) 	 //6,7,8
list2.foreach(println)   //原来集合元素不变 结果为:4,5,6,7,8

slice 截取某个区间的数据

var list=List(1,2,3,4,5)
list.slice(1,3).foreach(println)//结果为2,3-->返回(1,3]不包括1,包括3的新集合

reverse(翻转)

var list=List(1,2,3,4,5)
list.reverse.foreach(println) //结果为:5,4,3,2,1

take/takeRight

var list=List(1,2,3,4,5)
list.take(3).foreach(println)//获取集合前三个元素--> 1,2,3
list.takeRight(3).foreach(println)//获取集合后三个元素--> 3,4,5

takeWhile

从集合头部看来是匹配,遇到第一个false则终止

var list=List(1,2,3,4,5)
list.takeWhile(x=> x<4).foreach(println) //从头匹配,遇到第一个false则终止--> 1,2,3

head

获取集合中第一个元素

var list=List(1,2,3,4,5)
println(list.head) //获取集合中第一个元素-->结果为:1

tail

获取集合中除去第一个元素以外的全部元素

var list=List(1,2,3,4,5)
println(list.tail)//获取集合中除去第一个元素以外的全部元素 -->结果为:(2,3,4,5)

ListBuffer(可变集合)

def main(args: Array[String]): Unit = {
    var list=ListBuffer[Int]()
    list.+=(1)
    list.+=(2,3,4,5)  //ListBuffer是可变的集合
    list.update(1,6)  //将下标1的元素修改成6
    list.remove(0)    //删除指定下表的元素
    list.insert(0,7)  //在指定位置添加元素
    list.insertAll(0,List(11,12,13))  //在指定位置插入一个集合
    list++=(List(21,22,23)) //在集合后面追加一个集合
    list.+=(24)             //在集合最后追加一个元素
    list.-=(23)             //在几何中删除指定元素
    list--=List(1,2,3)      //在集合中删除一个集合
    println(list.size)      //返回集合的长度
    println(list.length)    //返回集合的长度
    println(list.sum)       //返回集合中全部元素的和
    list.foreach(println)
  }

Set(不可变)

scala.collection.immutable.Set

scala> var s=Set(1,2,3)
s: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala>      s += 4
res88: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)
scala>      s++=(List(4,5,6))
res89: scala.collection.immutable.Set[Int] = Set(1, 5, 2, 6, 3, 4)
scala>      s-=(3)
res90: scala.collection.immutable.Set[Int] = Set(1, 5, 2, 6, 4)
scala> s.size
res91: Int = 5
scala> s.sum
res92: Int = 18
scala> s.ma
map   mapResult   max   maxBy
scala> s.max
res93: Int = 6
scala> s.min
res94: Int = 1

Set(可变)

scala.collection.mutable.Set

scala> var s=scala.collection.mutable.Set(1,2,3)
s: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
scala>      s += 4
res99: scala.collection.mutable.Set[Int] = Set(1, 2, 3, 4)
scala>      s++=(List(4,5,6))
res100: scala.collection.mutable.Set[Int] = Set(1, 5, 2, 6, 3, 4)
scala>      s-=(3)
res101: scala.collection.mutable.Set[Int] = Set(1, 5, 2, 6, 4)
scala>      s.remove(6)
res102: Boolean = true
scala>      s.add(9)
res103: Boolean = true
scala> s.size
res104: Int = 5
scala> s.sum
res105: Int = 21
scala> s.min
res106: Int = 1
scala> s.max
res107: Int = 9

HashMap(不可变)

scala.collection.immutable.HashMap

scala> var hm=HashMap[String,String](("建设","001"),("招商","002"))
hm: scala.collection.immutable.HashMap[String,String] = Map(建设 -> 001, 招商 -> 002)

scala>      hm+="工商"->"003" //等价hm+=("工商","003")

scala>      hm-=("工商")

scala>      val value:Option[String] = hm.get("建设")
value: Option[String] = Some(001)

scala>      println(value.getOrElse(""))
001

scala> 

scala>      hm.size
res3: Int = 2

scala> for(i<- hm) println(i._1+" -> "+i._2)
建设 -> 001
招商 -> 002
scala> var hm=HashMap[String,String](("建设","001"),("招商","002"))
hm: scala.collection.immutable.HashMap[String,String] = Map(建设 -> 001, 招商 -> 002)

scala>      hm+="工商"->"003"

scala>      hm-=("工商")

scala>      //高阶函数

scala>      var mergerFunction:((String,String),(String,String))=>(String,String)=(tuple1,tuple2)=>{ 
     |          println(tuple1+" -> "+tuple2)
     |          if(tuple1._1.equals(tuple2._1)){
     |               (tuple1._1,tuple2._2)
     |          }else{
     |                tuple1
     |          }
     |      }
mergerFunction: ((String, String), (String, String)) => (String, String) = $$Lambda$1152/2052572633@742aa00a

scala>      var newhm=HashMap[String,String](("邮政","004"))
newhm: scala.collection.immutable.HashMap[String,String] = Map(邮政 -> 004)

scala>      var res=hm.merged(newhm)(mergerFunction)
res: scala.collection.immutable.HashMap[String,String] = Map(邮政 -> 004, 建设 -> 001, 招商 -> 002)

scala>      for(i<- res) println(i)
(邮政,004)
(建设,001)
(招商,002)

HashMap(可变)

scala.collection.mutable.HashMap

import scala.collection.mutable

object TestHashMap {
  def main(args: Array[String]): Unit = {
    var map=mutable.HashMap[String,String](("001","Lijb"),("002","Houy"))
    map+="003"->"Donghy" //添加一个元组/键值对
    map-="003"           //根据健删除键值对
    map.put("004","Gex") //添加一个元组/键值对
    map.remove("004")    //根据健删除键值对
    //遍历方式
    map.foreach(t=>println(t._1+"->"+t._2))
    map.foreach(println)
    for(i<- map) println(i)
  }
}

数组集合经常使用方法

排 序

sorted sortBy() sortWith()

def main(args: Array[String]): Unit = {
    var arr=Array (8,7,3,4,5)
    arr.sorted.foreach(println)//升序排序
    var arr1=Array(("a",1),("c",2),("b",3),("d",5))
    arr1.sortBy(t=>t._1)  //等价list.sortBy(_._1)
    arr1.sortWith((t1,t2)=>t1._2<t2._2)
    arr1.foreach(println)
  }

数组展开

flatten

def main(args: Array[String]): Unit = {
    var list=List(Array("a","c"),Array("d","b"))
    list.flatten.foreach(println) //a,c,d,b
  }

转换

map方法将一个函数应用到某个集合的全部元素并返回结果;

foreach将函数应用到每一个元素。

scala> var lst=List("hello world","good good study","day day up")
lst: List[String] = List(hello world, good good study, day day up)

scala> lst.map(item=>item.split(" "))
res15: List[Array[String]] = List(Array(hello, world), Array(good, good, study), Array(day, day, up))
scala>lst.map(item=>item.split(" ")).flatten
res16: List[String] = List(hello, world, good, good, study, day, day, up)

转换并展开

flatMap

scala> lst.flatMap(item=>item.split(" "))
res19: List[String] = List(hello, world, good, good, study, day, day, up)

scala> lst.flatMap(_.split(" "))
res20: List[String] = List(hello, world, good, good, study, day, day, up)

过滤

filter方法输出全部匹配某个特定条件的元素:

scala> var lst=List("hello world","good good study","day day up")
lst: List[String] = List(hello world, good good study, day day up)

scala> lst.flatMap(_.split(" ")).filter(_.equals("good"))
res22: List[String] = List(good, good)

元组排序

scala> var lst=Array(("a",1),("c",4),("b",3),("d",2))
lst: Array[(String, Int)] = Array((a,1), (c,4), (b,3), (d,2))

scala> lst.sorted
res9: Array[(String, Int)] = Array((a,1), (b,3), (c,4), (d,2))

scala> lst.sortBy(x=>x._2)
res11: Array[(String, Int)] = Array((a,1), (d,2), (b,3), (c,4))

定制排序规则

scala> var lst=Array(("a",1),("c",4),("b",3),("d",2))
lst: Array[(String, Int)] = Array((a,1), (c,4), (b,3), (d,2))

scala> lst.sortWith((x,y)=> {x._1>y._1} )
res12: Array[(String, Int)] = Array((d,2), (c,4), (b,3), (a,1))

分组统计

scala> var lst=Array("a","b","d","c","b","a","d","d")
lst: Array[String] = Array(a, b, d, c, b, a, d, d)

scala>    lst.groupBy(x=>x)
res51: scala.collection.immutable.Map[String,Array[String]] = Map(b -> Array(b,
b), d -> Array(d, d, d), a -> Array(a, a), c -> Array(c))

scala> var lst=Array(("a",1),("b",2),("a",2))
lst.groupBy(x=>x._1).map(x=>(x._1,(for(i <- x._2) yield i._2).sum))

fold统计

var lst=Array(Array(1,2,3),Array(1,2,4),Array(5,6,7),Array(9,4))
lst.flatten.fold(0)((x,y)=>x+y)//结果44  全部元素的和

aggregate

scala>  var lst=List(1,2,4,5,6)
lst: List[Int] = List(1, 2, 4, 5, 6)
                  初始值  局部计算    汇总逻辑
scala> lst.aggregate(0)((x,y)=>x+y,(x,y)=>x+y) //等价 lst.aggregate(2)(_+_,_+_)
res11: Int = 18

Reduce

scala> var lst=List(1,2,4,5,6)
lst: List[Int] = List(1, 2, 4, 5, 6)

scala>      lst.reduce(_+_)
res12: Int = 18

group

cala> var lst=Array(1,2,4,5,6,7)
lst: Array[Int] = Array(1, 2, 4, 5, 6, 7)

scala> lst.grouped(3).toList //将数组按给定长度分红若干分数组而且组合成一个集合
res18: List[Array[Int]] = List(Array(1, 2, 4), Array(5, 6, 7))

zip

scala> var v=Vector(1,2,4)
v: scala.collection.immutable.Vector[Int] = Vector(1, 2, 4)

scala> v.zip(Array("a","b","c"))
res22: scala.collection.immutable.Vector[(Int, String)] = Vector((1,a), (2,b), (4,c))

unizp

scala> var v=List(("a",1),("b",2),("c",3))
v: List[(String, Int)] = List((a,1), (b,2), (c,3))

scala> v.unzip
res24: (List[String], List[Int]) = (List(a, b, c),List(1, 2, 3))

diff | intersect | union

scala>  var v=List(1,2,3)
v: List[Int] = List(1, 2, 3)

scala>      v.diff(List(2,3,5))	//diff求并集
res27: List[Int] = List(1)

scala> var v=List(1,2,3,5)
v: List[Int] = List(1, 2, 3, 5)

scala>      v.intersect(List(2,4,6))	//intersert求交集
res37: List[Int] = List(2)

scala>  var v=List(1,2,3,5)
v: List[Int] = List(1, 2, 3, 5)

scala>      v.union(List(2,4,6))	//两集合进行合并
res0: List[Int] = List(1, 2, 3, 5, 2, 4, 6)

distinct

scala> var v=List(1,2,3,3,5)
v: List[Int] = List(1, 2, 3, 3, 5)

scala>      v.distinct	//去重
res29: List[Int] = List(1, 2, 3, 5)

Sliding

scala> var v=List(1,2,3,3,5)
v: List[Int] = List(1, 2, 3, 3, 5)
scala>      v.sliding(2,1).toList	//交叉一个元素,每一个集合两个元素
res35: List[List[Int]] = List(List(1, 2), List(2, 3), List(3, 3), List(3, 5))

数组集合方法的应用场景

字符统计

def main(args: Array[String]): Unit = {
    var arrs=Array("this is a Statistical demo","good good study","day day up")
    arrs.map(_.split(" "))  // 按""分割
      .flatten  //将元素展开
      .map((_,1)) //将集合中的元素统计+1
      .groupBy(_._1)//按照每个元组的第一个元素(也就是不重复的每个单词)分类
      .map(x=>(x._1,(for(i<- x._2) yield i._2.toInt)//遍历map,而且遍历map里的值算其长度,并提取出来
        .toList.sum))//进行相加统计
      .toList
      .sortBy(_._1)
      .foreach(println)
  }

文件字符统计

def main(args: Array[String]): Unit = {
    var source=Source.fromFile("D:\\t_word.txt")
    var array=ArrayBuffer[String]();
    val breaks=Breaks
    breaks.breakable({
      val reader = source.bufferedReader()
      while(true){
        val line = reader.readLine()
        if(line==null){
          breaks.break()
        }
        array+=line
      }
    })
    array.flatMap(_.split(" "))
      .map((_,1))
      .groupBy(_._1)
      .map(x=>(x._1,x._2.size))
      .toList
      .sortBy(_._1)
      . foreach(println)

  }
相关文章
相关标签/搜索