目录

Scala - 快速指南

Scala - Overview

Scala是Scalable Language的缩写,是一种混合函数式编程语言。 它由Martin Odersky创建。 Scala顺利地集成了面向对象和功能语言的功能。 编译Scala以在Java虚拟机上运行。 许多依赖Java用于业务关键型应用程序的现有公司正在转向使用Scala来提高其开发效率,应用程序可伸缩性和整体可靠性。

在这里,我们提出了几点使Scala成为应用程序开发人员的首选。

Scala是面向对象的

Scala是一种纯粹的面向对象语言,因为每个值都是一个对象。 对象的类型和行为由类和特征描述,这将在后续章节中解释。

通过subclassing和灵活mixin-based composition机制来扩展subclassing ,作为多重继承的干净替代。

Scala很实用

Scala也是一种函数式语言,因为每个函数都是一个值,每个值都是一个对象,所以最终每个函数都是一个对象。

Scala提供了一种用于定义anonymous functions的轻量级语法,它支持higher-order functions ,它允许函数nested ,并支持currying 。 这些概念将在后续章节中解释。

Scala是静态类型的

与其他一些静态类型语言(C,Pascal,Rust等)不同,Scala不希望您提供冗余类型信息。 在大多数情况下,您不必指定类型,并且您当然不必重复它。

Scala在JVM上运行

Scala编译为Java Byte Code,由Java虚拟机(JVM)执行。 这意味着Scala和Java具有通用的运行时平台。 您可以轻松地从Java迁移到Scala。

Scala编译器将您的Scala代码编译为Java字节代码,然后可以通过' scala '命令执行。 ' scala '命令类似于java命令,因为它执行编译的Scala代码。

Scala可以执行Java代码

Scala使您可以使用Java SDK的所有类以及您自己的自定义Java类或您喜欢的Java开源项目。

Scala可以执行并发和同步处理

Scala允许您以有效的方式表达通用编程模式。 它减少了行数并帮助程序员以类型安全的方式进行编码。 它允许您以不可变的方式编写代码,这使得应用并发和并行(Synchronize)变得容易。

Scala与Java

Scala具有一系列与Java完全不同的功能。 其中一些是 -

  • All types are objects
  • Type inference
  • 嵌套函数
  • 功能是对象
  • 域特定语言(DSL)支持
  • Traits
  • Closures
  • Erlang启发的并发支持

Scala Web框架

Scala在各地都得到了使用,而且在企业Web应用程序中也很重要。 您可以查看一些最流行的Scala Web框架 -

Scala - Environment Setup

Scala可以安装在任何UNIX风格或基于Windows的系统上。 在计算机上开始安装Scala之前,必须在计算机上安装Java 1.8或更高版本。

按照下面给出的步骤安装Scala。

第1步:验证您的Java安装

首先,您需要在系统上安装Java软件开发工具包(SDK)。 要验证这一点,请根据您正在使用的平台执行以下两个命令中的任何一个。

如果Java安装已正确完成,那么它将显示Java安装的当前版本和规范。 下表给出了示例输出。

平台 命令 样本输出
Windows

打开命令控制台并输入 -

\》java –version

Java版“1.8.0_31”

Java(TM)SE运行时

环境(建立1.8.0_31-b31)

Java Hotspot(TM)64位服务器

VM(build 25.31-b07,混合模式)

Linux

打开命令终端并输入 -

$java –version

Java版“1.8.0_31”

打开JDK运行时环境(rhel-2.8.10.4.el6_4-x86_64)

打开JDK 64位服务器VM(内置25.31-b07,混合模式)

我们假设本教程的读者在其系统上安装了Java SDK版本1.8.0_31。

如果您没有Java SDK,请从http://www.oracle.com/technetwork/java/javase/downloads/index.html下载其当前版本并安装它。

第2步:设置Java环境

将环境变量JAVA_HOME设置为指向计算机上安装Java的基本目录位置。 例如,

Sr.No 平台和描述
1

Windows

将JAVA_HOME设置为C:\ProgramFiles\java\jdk1.7.0_60

2

Linux

导出JAVA_HOME =/usr/local/java-current

将Java编译器位置的完整路径附加到系统路径。

Sr.No 平台和描述
1

Windows

将字符串“C:\Program Files\Java\jdk1.7.0_60\bin”附加到系统变量PATH的末尾。

2

Linux

导出PATH = $ PATH:$ JAVA_HOME/bin/

如上所述,从命令提示符执行命令java -version

第3步:安装Scala

您可以从http://www.scala-lang.org/downloads下载Scala。 在编写本教程时,我下载了“scala-2.11.5-installer.jar”。 确保您具有管理员权限才能继续。 现在,在命令提示符下执行以下命令 -

平台 命令与输出 描述
Windows

\> java -jar scala-2.11.5-installer.jar \>

此命令将显示安装向导,该向导将指导您在Windows计算机上安装Scala。 在安装过程中,它会要求许可协议,只需接受它,并进一步询问将安装Scala的路径。 我选择了默认的给定路径“C:\Program Files\Scala”,您可以根据自己的方便选择合适的路径。

Linux

Command -

$ java -jar scala-2.9.0.1-installer.jar

Output -

欢迎安装Scala 2.9.0.1!

主页位于 - http://Scala-lang.org/

按1继续,2退出,3再重新显示

1 ................................................

[开始打开包装]

[处理包:软件包安装(1/1)]

[打开包装]

[控制台安装完成]

在安装过程中,它将要求许可协议,接受类型1,它将询问将安装Scala的路径。 我输入/usr/local/share,您可以根据自己的方便选择合适的路径。

最后,打开一个新的命令提示符并键入Scala -version并按Enter键。 您应该看到以下内容 -

平台 命令 output
Windows

\> scala -version

Scala代码运行器版本2.11.5 - 版权所有2002-2013,LAMP/EPFL

Linux

$ scala -version

Scala代码运行器版本2.9.0.1 - 版权所有2002-2013,LAMP/EPFL

Scala - Basic Syntax

如果您对Java有很好的理解,那么学习Scala将非常容易。 Scala和Java之间最大的语法区别是';' 行结束字符是可选的。

当我们考虑Scala程序时,它可以被定义为通过调用彼此的方法进行通信的对象集合。 现在让我们简要地看一下类,对象,方法和实例变量的含义。

  • Object - 对象具有状态和行为。 对象是类的实例。 示例 - 狗具有状态 - 颜色,名称,品种以及行为 - 摇摆,吠叫和进食。

  • Class - 可以将类定义为描述与类相关的行为/状态的模板/蓝图。

  • Methods - 方法基本上是一种行为。 一个类可以包含许多方法。 它是在编写逻辑,操纵数据并执行所有操作的方法中。

  • Fields - 每个对象都有其唯一的实例变量集,称为字段。 对象的状态由分配给这些字段的值创建。

  • Closure - closure是一个函数,其返回值取决于在此函数外声明的一个或多个变量的值。

  • Traits - 特征封装了方法和字段定义,然后可以通过将它们混合到类中来重用它们。 Traits用于通过指定支持的方法的签名来定义对象类型。

第一个Scala计划

我们可以在两种模式下执行Scala程序:一种是interactive mode ,另一种是script mode

互动模式

打开命令提示符并使用以下命令打开Scala。

\>scala

如果您的系统中安装了Scala,将显示以下输出 -

Welcome to Scala version 2.9.0.1
Type in expressions to have them evaluated.
Type :help for more information.

在Scala提示符右侧键入以下文本,然后按Enter键 -

scala> println("Hello, Scala!");

它会产生以下结果 -

Hello, Scala!

脚本模式

使用以下说明以脚本模式编写Scala程序。 打开记事本并将以下代码添加到其中。

例子 (Example)

object HelloWorld {
   /* This is my first java program.  
   * This will print 'Hello World' as the output
   */
   def main(args: Array[String]) {
      println("Hello, world!") // prints Hello World
   }
}

将文件另存为 - HelloWorld.scala

打开命令提示符窗口,转到保存程序文件的目录。 ' scalac '命令用于编译Scala程序,它将在当前目录中生成一些类文件。 其中一个将被称为HelloWorld.class 。 这是一个字节码,它将使用' scala '命令在Java虚拟机(JVM)上运行。

使用以下命令编译和执行Scala程序。

\> scalac HelloWorld.scala
\> scala HelloWorld

输出 (Output)

Hello, World!

基本语法

以下是Scala编程中的基本语法和编码约定。

  • Case Sensitivity - Scala区分大小写,这意味着标识符Hellohello在Scala中具有不同的含义。

  • Class Names - 对于所有类名,第一个字母应为大写。 如果使用多个单词来形成类的名称,则每个内部单词的第一个字母应为大写。

    Example - 类MyFirstScalaClass。

  • Method Names - 所有方法名称都应以小写字母开头。 如果使用多个单词来形成方法的名称,那么每个内部单词的第一个字母应该是大写字母。

    Example - def myMethodName()

  • Program File Name - Program File Name应与对象名称完全匹配。 保存文件时,应使用对象名称保存它(记住Scala区分大小写)并在名称末尾附加“ .scala ”。 (如果文件名和对象名不匹配,则程序将无法编译)。

    Example - 假设'HelloWorld'是对象名称。 然后该文件应保存为“HelloWorld.scala”。

  • def main(args: Array[String]) - Scala程序处理从main()方法开始,该方法是每个Scala程序的必需部分。

Scala标识符

所有Scala组件都需要名称。 用于对象,类,变量和方法的名称称为标识符。 关键字不能用作标识符,标识符区分大小写。 Scala支持四种类型的标识符。

字母数字标识符

字母数字标识符以字母或下划线开头,后面可以跟其他字母,数字或下划线。 '$'字符是Scala中的保留关键字,不应在标识符中使用。

以下是legal alphanumeric identifiers -

age, salary, _value,  __1_value

以下是illegal identifiers -

$salary, 123abc, -salary

运算符标识符

运算符标识符由一个或多个运算符字符组成。 运算符字符是可打印的ASCII字符,例如+,:,?,〜或#。

以下是合法运算符标识符 -

+ ++ ::: <?> :>

Scala编译器将在内部“修改”运算符标识符,将它们转换为嵌入了$字符的合法Java标识符。 例如,标识符: - >将在内部表示为$ colon $ minus $ greater。

混合标识符

混合标识符由字母数字标识符组成,后跟下划线和运算符标识符。

以下是合法的混合标识符 -

unary_+,  myvar_=

这里,用作方法名称的unary_ +定义一元+运算符,用作方法名称的myvar_ =定义赋值运算符(运算符重载)。

文字标识符

文字标识符是后面的标记(`...``)中包含的任意字符串。

以下是法律文字标识符 -

`x` `<clinit>` `yield`

Scala关键词

以下列表显示了Scala中的保留字。 这些保留字不能用作常量或变量或任何其他标识符名称。

abstractcasecatchclass
defdoelseextends
falsefinalfinallyfor
forSomeifimplicitimport
lazymatchnewNull
objectoverridepackageprivate
protectedreturnsealedsuper
thisthrowtraitTry
truetypevalVar
whilewithyield
-:==>
<-<:<%>:
#@

Scala中的评论

Scala支持与Java非常相似的单行和多行注释。 多行注释可以嵌套,但需要正确嵌套。 Scala编译器会忽略任何注释中可用的所有字符。

object HelloWorld {
   /* This is my first java program.  
    * This will print 'Hello World' as the output
    * This is an example of multi-line comments.
    */
   def main(args: Array[String]) {
      // Prints Hello World
      // This is also an example of single line comment.
      println("Hello, world!") 
   }
}

空白行和空白

只包含空格(可能带有注释)的行称为空行,Scala完全忽略它。 标记可以用空格字符和/或注释分隔。

换行符

Scala是一种面向行的语言,语句可以用分号(;)或换行符终止。 语句末尾的分号通常是可选的。 如果需要,可以键入一个,但如果语句单独出现在一行中,则不必输入。 另一方面,如果在一行上写多个语句,则需要分号。 下面的语法是多个语句的用法。

val s = "hello"; println(s)

Scala包

包是命名的代码模块。 例如,Lift实用程序包是net.liftweb.util。 包声明是源文件中的第一个非注释行,如下所示 -

package com.liftcode.stuff

可以导入Scala包,以便可以在当前编译范围中引用它们。 以下语句导入scala.xml包的内容 -

import scala.xml._

您可以从scala.collection.mutable包导入单个类和对象,例如HashMap -

import scala.collection.mutable.HashMap

您可以从单个包导入多个类或对象,例如,scala.collection.immutable包中的TreeMap和TreeSet -

import scala.collection.immutable.{TreeMap, TreeSet}

应用动态

标记特征,可启用动态调用。 此特征的实例x允许方法调用x.meth(args)用于任意方法名称meth和参数列表args以及字段访问x.field用于任意字段名称字段。 Scala-2.10中引入了此功能。

如果x本身不支持调用(即,如果类型检查失败),则根据以下规则重写它 -

foo.method("blah") ~~> foo.applyDynamic("method")("blah")
foo.method(x = "blah") ~~> foo.applyDynamicNamed("method")(("x", "blah"))
foo.method(x = 1, 2) ~~> foo.applyDynamicNamed("method")(("x", 1), ("", 2))
foo.field ~~> foo.selectDynamic("field")
foo.varia = 10 ~~> foo.updateDynamic("varia")(10)
foo.arr(10) = 13 ~~> foo.selectDynamic("arr").update(10, 13)
foo.arr(10) ~~> foo.applyDynamic("arr")(10)

Scala - Data Types

Scala具有与Java相同的所有数据类型,具有相同的内存占用和精度。 以下表格提供了Scala中可用的所有数据类型的详细信息 -

Sr.No 数据类型和描述
1

Byte

8位有符号值。 范围从-128到127

2

Short

16位有符号值。 范围-32768到32767

3

Int

32位有符号值。 范围-2147483648至2147483647

4

Long

64位有符号值。 -9223372036854775808至9223372036854775807

5

Float

32位IEEE 754单精度浮点数

6

Double

64位IEEE 754双精度浮点数

7

Char

16位无符号Unicode字符。 范围从U + 0000到U + FFFF

8

String

一系列的Chars

9

Boolean

无论是文字真实还是文字虚假

10

Unit

对应没有价值

11

Null

null或空引用

12

Nothing

每种其他类型的子类型; 不包括任何价值

13

Any

任何类型的超类型; 任何对象都是Any类型

14

AnyRef

任何引用类型的超类型

上面列出的所有数据类型都是对象。 Java中没有原始类型。 这意味着您可以在Int,Long等上调用方法。

Scala Basic Literals

Scala用于文字的规则简单直观。 本节介绍所有基本的Scala文字。

积分文字

整数文字通常是Int类型,或者类型为Long,后跟L或l后缀。 这是一些整数文字 -

0
035
21 
0xFFFFFFFF 
0777L

浮点文字

浮点文字的类型为Float,后跟浮点类型后缀F或f,否则为Double类型。 这里有一些浮点文字 -

0.0 
1e30f 
3.14159f 
1.0e100
.1

布尔文字

布尔文字truefalse是Boolean类型的成员。

符号文字

符号文字'x是表达式scala.Symbol("x")的简写。 符号是一个案例类,定义如下。

package scala
final case class Symbol private (name: String) {
   override def toString: String = "'" + name
}

字符文字

字符文字是用引号括起来的单个字符。 该字符是可打印的Unicode字符或由转义序列描述。 这是一些字符文字 -

'a' 
'\u0041'
'\n'
'\t'

字符串文字

字符串文字是双引号中的字符序列。 字符是可打印的Unicode字符或由转义序列描述。 这是一些字符串文字 -

"Hello,\nWorld!"
"This string contains a \" character."

Multi-Line Strings

多行字符串文字是用三引号“”“......”“”括起来的字符序列。 字符序列是任意的,除了它可能只在最后包含三个或更多连续引号字符。

字符不一定是可打印的; 也允许换行或其他控制字符。 这是一个多行字符串文字 -

"""the present string
spans three
lines."""

空值

null值的类型为scala.Null ,因此与每个引用类型兼容。 它表示引用特殊“空”对象的引用值。

转义序列 (Escape Sequences)

在字符和字符串文字中可识别以下转义序列。

转义序列 统一 描述
\b\u0008backspace BS
\t\u0009horizontal tab HT
\n\u000c formfeed FF
\f\u000c formfeed FF
\r\u000dcarriage return CR
\"\u0022double quote "
\'\u0027single quote .
\\\u005c backslash (反斜杠)

Unicode在0到255之间的字符也可以用八进制转义表示,即反斜杠“\”后跟最多三个八进制字符的序列。 以下是显示少数转义序列字符的示例 -

例子 (Example)

object Test {
   def main(args: Array[String]) {
      println("Hello\tWorld\n\n" );
   }
} 

编译并执行上述代码时,会产生以下结果 -

输出 (Output)

Hello   World

Scala - Variables

变量只是用于存储值的保留内存位置。 这意味着在创建变量时,会在内存中保留一些空间。

根据变量的数据类型,编译器分配内存并决定可以存储在保留内存中的内容。 因此,通过为变量分配不同的数据类型,可以在这些变量中存储整数,小数或字符。

变量声明 (Variable Declaration)

Scala具有用于声明变量的不同语法。 它们可以定义为值,即常量或变量。 这里,使用关键字var声明myVar。 它是一个可以改变值的变量,这被称为mutable variable 。 以下是使用var关键字定义变量的语法 -

语法 (Syntax)

var myVar : String = "Foo"

这里,使用关键字val声明myVal。 这意味着它是一个无法更改的变量,这称为immutable variable 。 以下是使用val关键字定义变量的语法 -

语法 (Syntax)

val myVal : String = "Foo"

可变数据类型

变量的类型在变量名之后和等号之前指定。 您可以通过提及其数据类型来定义任何类型的Scala变量,如下所示 -

语法 (Syntax)

val or val VariableName : DataType = [Initial Value]

如果您没有为变量分配任何初始值,则它有效如下 -

语法 (Syntax)

var myVar :Int;
val myVal :String;

变量类型推断

为变量分配初始值时,Scala编译器可以根据分配给它的值来计算变量的类型。 这称为变量类型推断。 因此,您可以像这样编写这些变量声明 -

语法 (Syntax)

var myVar = 10;
val myVal = "Hello, Scala!";

这里,默认情况下,myVar将是Int类型,myVal将成为String类型变量。

多项任务

Scala支持多项任务。 如果代码块或方法返回一个元组( Tuple - 保持不同类型的对象的集合),则可以将元组分配给val变量。 [ Note - 我们将在后续章节中学习元组。]

语法 (Syntax)

val (myVar1: Int, myVar2: String) = Pair(40, "Foo")

类型推断得到了正确的答案 -

语法 (Syntax)

val (myVar1, myVar2) = Pair(40, "Foo")

示例程序

以下是解释Scala中变量声明过程的示例程序。 该程序声明了四个变量 - 两个变量用变量声明定义,剩下两个变量没有变量声明。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      var myVar :Int = 10;
      val myVal :String = "Hello Scala with datatype declaration.";
      var myVar1 = 20;
      val myVal1 = "Hello Scala new without datatype declaration.";
      println(myVar); println(myVal); println(myVar1); 
      println(myVal1);
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

10
Hello Scala with datatype declaration.
20
Hello Scala without datatype declaration.

可变范围

Scala中的变量可以有三种不同的范围,具体取决于它们的使用位置。 它们可以作为字段,方法参数和局部变量存在。 以下是每种范围的详细信息。

Fields

字段是属于对象的变量。 可以从对象中的每个方法内部访问这些字段。 字段也可以在对象外部访问,具体取决于声明字段的访问修饰符。 对象字段既可以是可变类型也可以是不可变类型,可以使用varval定义。

方法参数

方法参数是变量,用于在调用方法时在方法内传递值。 方法参数只能从方法内部访问,但是如果从方法外部引用了对象,则可以从外部访问传入的对象。 方法参数总是不可变的,由val关键字定义。

局部变量

局部变量是在方法内声明的变量。 局部变量只能从方法内部访问,但是如果从方法返回,则创建的对象可能会转义该方法。 局部变量既可以是可变类型也可以是不可变类型,可以使用varval定义。

Scala - Classes & Objects

本章将向您介绍如何在Scala编程中使用类和对象。 类是对象的蓝图。 定义类后,可以使用关键字new从类蓝图创建对象。 通过该对象,您可以使用已定义类的所有功能。

下图以类student为例演示了类和对象,其中包含成员变量(name和roll no)和成员方法(setName()和setRollNo())。 最后所有人都是班上的成员。 类是蓝色打印,对象在这里是真实的。 在下图中,Student是一个类,Harini,John和Maria是Student类的对象,它们具有名称和roll-number。

Scala类和对象

基础班

以下是在Scala中定义基本类的简单语法。 此类定义了两个变量xy以及一个方法: move ,它不返回值。 调用类变量,类的字段和方法称为类方法。

类名作为类构造函数,可以使用许多参数。 上面的代码定义了两个构造函数参数, xcyc ; 它们在全班同学中都可见。

语法 (Syntax)

class Point(xc: Int, yc: Int) {
   var x: Int = xc
   var y: Int = yc
   def move(dx: Int, dy: Int) {
      x = x + dx
      y = y + dy
      println ("Point x location : " + x);
      println ("Point y location : " + y);
   }
}

如本章前面所述,您可以使用关键字new创建对象,然后您可以访问类字段和方法,如下例所示 -

例子 (Example)

import java.io._
class Point(val xc: Int, val yc: Int) {
   var x: Int = xc
   var y: Int = yc
   def move(dx: Int, dy: Int) {
      x = x + dx
      y = y + dy
      println ("Point x location : " + x);
      println ("Point y location : " + y);
   }
}
object Demo {
   def main(args: Array[String]) {
      val pt = new Point(10, 20);
      // Move to a new location
      pt.move(10, 10);
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Point x location : 20
Point y location : 30

扩展课程

您可以扩展基础Scala类,并且可以像在Java中一样设计继承类(使用extends关键字),但有两个限制:方法重写需要override关键字,并且只有primary构造函数可以通过基础构造函数的参数。 让我们扩展上面的类并添加一个类方法。

例子 (Example)

让我们举两个类Point类的例子(与上面相同的例子)和Location类是使用extends关键字继承的类。 这样的' extends '子句有两个作用:它使Location类从Point类继承所有非私有成员,并使类型Location成为Point类的子类型。 因此,Point类称为superclass ,类Location称为subclass 。 扩展类并继承父类的所有功能称为inheritance但Scala仅允许从一个类继承。

Note - Point类中的方法move()方法和move() method in Location class不会覆盖move的相应定义,因为它们是不同的定义(例如,前者采用两个参数,后者采用三个参数)。

请尝试以下示例程序来实现继承。

import java.io._
class Point(val xc: Int, val yc: Int) {
   var x: Int = xc
   var y: Int = yc
   def move(dx: Int, dy: Int) {
      x = x + dx
      y = y + dy
      println ("Point x location : " + x);
      println ("Point y location : " + y);
   }
}
class Location(override val xc: Int, override val yc: Int,
   val zc :Int) extends Point(xc, yc){
   var z: Int = zc
   def move(dx: Int, dy: Int, dz: Int) {
      x = x + dx
      y = y + dy
      z = z + dz
      println ("Point x location : " + x);
      println ("Point y location : " + y);
      println ("Point z location : " + z);
   }
}
object Demo {
   def main(args: Array[String]) {
      val loc = new Location(10, 20, 15);
      // Move to a new location
      loc.move(10, 10, 5);
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Point x location : 20
Point y location : 30
Point z location : 20

隐式类

当类在范围内时,隐式类允许与类的主构造函数进行隐式对话。 隐式类是标有“隐式”关键字的类。 Scala 2.10中引入了此功能。

Syntax - 以下是隐式类的语法。 这里隐式类总是在允许所有方法定义的对象范围内,因为隐式类不能是顶级类。

语法 (Syntax)

object <object name> {
   implicit class <class name>(<Variable>: Data type) {
      def <method>(): Unit =
   }
}

例子 (Example)

让我们举一个名为IntTimes的隐式类,其方法为times()。 这意味着times()包含一个循环事务,它将按照我们给出的次数执行给定的语句。 让我们假设给定的语句是“4次println(”Hello“)”表示println(“”Hello“)语句将执行4次。

以下是给定示例的程序。 在这个例子中,使用了两个对象类(Run和Demo),因此我们必须将这两个类保存在不同的文件中,它们各自的名称如下所示。

Run.scala - 在Run.scala中保存以下程序。

object Run {
   implicit class IntTimes(x: Int) {
      def times [A](f: =>A): Unit = {
         def loop(current: Int): Unit =
         if(current > 0){
            f
            loop(current - 1)
         }
         loop(x)
      }
   }
}

Demo.scala - 在Demo.scala中保存以下程序。

import Run._
object Demo {
   def main(args: Array[String]) {
      4 times println("hello")
   }
}

以下命令用于编译和执行这两个程序。

Command

\>scalac Run.scala
\>scalac Demo.scala
\>scala Demo

输出 (Output)

Hello
Hello
Hello
Hello

Note -

  • 隐式类必须在另一个类/对象/特征内定义(不在顶层)。

  • 隐式类只能在其构造函数中使用一个非隐式参数。

  • 隐式类可能不是范围内与隐式类同名的任何方法,成员或对象。

单身对象

Scala比Java更面向对象,因为在Scala中,我们不能拥有静态成员。 相反,Scala具有singleton objects 。 单例是一个只能有一个实例的类,即Object。 您可以使用关键字object而不是class关键字创建单例。 由于无法实例化单例对象,因此无法将参数传递给主构造函数。 您已经看过使用单个对象的所有示例,其中您调用了Scala的main方法。

以下是实现单例的相同示例程序。

例子 (Example)

import java.io._
class Point(val xc: Int, val yc: Int) {
   var x: Int = xc
   var y: Int = yc
   def move(dx: Int, dy: Int) {
      x = x + dx
      y = y + dy
   }
}
object Demo {
   def main(args: Array[String]) {
      val point = new Point(10, 20)
      printPoint
      def printPoint{
         println ("Point x location : " + point.x);
         println ("Point y location : " + point.y);
      }
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Point x location : 10
Point y location : 20

Scala - Access Modifiers

本章将指导您完成Scala访问修饰符。 包,类或对象的成员可以使用访问修饰符私有和受保护标记,如果我们不使用这两个关键字中的任何一个,则访问将被假定为公共访问。 这些修饰符限制对成员到某些代码区域的访问。 要使用访问修饰符,请在包,类或对象的成员定义中包含其关键字,我们将在下一节中看到。

私人会员

私有成员仅在包含成员定义的类或对象内可见。

以下是解释私人会员的示例代码段 -

例子 (Example)

class Outer {
   class Inner {
      private def f() { println("f") }
      class InnerMost {
         f() // OK
      }
   }
   (new Inner).f() // Error: f is not accessible
}

在Scala中,访问(新内部)。 f()是非法的,因为f在Inner中声明为private,而访问不在Inner类内。 相比之下,在Innermost类中第一次访问f是可以的,因为该访问包含在Inner类的主体中。 Java允许两种访问,因为它允许外部类访问其内部类的私有成员。

受保护的会员

受保护的成员只能从定义成员的类的子类访问。

以下是解释受保护成员的示例代码段 -

例子 (Example)

package p {
   class Super {
      protected def f() { println("f") }
   }
   class Sub extends Super {
      f()
   }
   class Other {
      (new Super).f() // Error: f is not accessible
   }
}

在Sub类中访问f是正常的,因为f在'Super'类中被声明为受保护,而'Sub'类是Super的子类。 相比之下,不允许在“其他”类中访问f,因为“其他”类不会继承“超级”类。 在Java中,后一个访问仍然是允许的,因为'Other'类与'Sub'类在同一个包中。

公众成员

与私有成员和受保护成员不同,不需要为Public成员指定Public关键字。 公共成员没有明确的修饰符。 这些成员可以从任何地方访问。

以下是解释公共成员的示例代码段 -

例子 (Example)

class Outer {
   class Inner {
      def f() { println("f") }
      class InnerMost {
         f() // OK
      }
   }
   (new Inner).f() // OK because now f() is public
}

保护范围

Scala中的访问修饰符可以使用限定符进行扩充。 私有[X]或受保护[X]形式的修饰符意味着访问是私有的或受到“最多”X的保护,其中X表示一些封闭的包,类或单个对象。

考虑以下示例 -

例子 (Example)

package society {
   package professional {
      class Executive {
         private[professional] var workDetails = null
         private[society] var friends = null
         private[this] var secrets = null
         def help(another : Executive) {
            println(another.workDetails)
            println(another.secrets) //ERROR
         }
      }
   }
}

Note - 以上示例中的以下几点 -

  • 可以在封闭包专业人员中的任何类访问变量workDetails。

  • 封闭的包装社会中的任何类别都可以访问可变的朋友。

  • 只有实例方法中的隐式对象才能访问可变秘密(this)。

Scala - Operators

运算符是一个符号,告诉编译器执行特定的数学或逻辑操作。 Scala内置运算符丰富,提供以下类型的运算符 -

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 按位运算符
  • 分配运算符

本章将逐一检查算术,关系,逻辑,按位,赋值和其他运算符。

算术运算符 (Arithmetic Operators)

Scala语言支持以下算术运算符。 例如,让我们假设变量A保持10,变量B保持20,然后 -

显示示例

操作者 描述
+ 添加两个操作数 A + B将给出30
- 从第一个减去第二个操作数 A - B将给-10
* 将两个操作数相乘 A * B将给出200
/Divides numerator by de-numerator B/A会给2
% 模数运算符在将一个数字除以另一个数字之后找到余数 B%A将给出0

关系运算符 (Relational Operators)

Scala语言支持以下关系运算符。 例如,让我们假设变量A保持10,变量B保持20,然后 -

显示示例

操作者 描述
== 检查两个操作数的值是否相等,如果是,则条件变为真。 (A == B)不是真的。
!= 检查两个操作数的值是否相等,如果值不相等则条件变为真。 (A!= B)是真的。
> 检查左操作数的值是否大于右操作数的值,如果是,则条件变为真。 (A> B)不是真的。
< 检查左操作数的值是否小于右操作数的值,如果是,则条件变为真。 (A < B) 为真
>= 检查左操作数的值是否大于或等于右操作数的值,如果是,则条件变为真。 (A> = B)不是真的。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是,则条件变为真。 (A <= B)是真的。

逻辑运算符 (Logical Operators)

Scala语言支持以下逻辑运算符。 例如,假设变量A保持1而变量B保持0,则 -

显示示例

操作者 描述
&& 它被称为逻辑AND运算符。 如果两个操作数都不为零,则条件成立。 (A && B)是假的。
|| 它被称为逻辑OR运算符。 如果两个操作数中的任何一个不为零,则条件变为真。 (A || B)是真的。
! 它被称为逻辑非运算符。 用于反转其操作数的逻辑状态。 如果条件为真,则Logical NOT运算符将为false。 !(A && B)是真的。

按位运算符 (Bitwise Operators)

按位运算符处理位并执行逐位运算。 &,|和^的真值表如下 -

p q p&q p | q p ^ q
00000
01011
11110
10011

假设A = 60; 和B = 13; 现在以二进制格式,他们将如下 -

A = 0011 1100
B = 0000 1101
-----------------------
A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~A = 1100 0011

下表列出了Scala语言支持的Bitwise运算符。 假设变量A保持60,变量B保持13,则 -

显示示例

操作者 描述
& 如果二进制AND运算符存在于两个操作数中,则它会将结果复制到结果中。 (A&B)将给出12,即0000 1100
| 二进制OR运算符如果存在于任一操作数中,则复制一位。 (A | B)将给出61,即0011 1101
^ 二进制异或运算符如果在一个操作数中设置但不在两个操作数中设置,则复制该位。 (A ^ B)将给出49,即0011 0001
~ 二元一元补语运算符是一元的,具有“翻转”位的效果。 (~A)将给出-61,由于带符号的二进制数,它是2的补码形式的1100 0011。
<< 二进制左移运算符。 左操作数值的位位置向左移动右操作数指定的位数。 A << 2将给出240,即1111 0000
>> 二进制右移运算符。 左操作数值的位位置向右移动右操作数指定的位数。 A >> 2将给出15,即1111
>>> 右移零填充运算符。 左操作数值向右移动右操作数指定的位数,移位值用零填充。 A >>> 2将给出15,即0000 1111

赋值操作符 (Assignment Operators)

Scala语言支持以下赋值运算符 -

显示示例

操作者 描述
= 简单赋值运算符,将右侧操作数的值分配给左侧操作数 C = A + B将A + B的值分配给C
+= 添加AND赋值运算符,它将右操作数添加到左操作数并将结果赋给左操作数 C + = A等于C = C + A.
-= 减去AND赋值运算符,它从左操作数中减去右操作数,并将结果赋给左操作数 C - = A相当于C = C - A.
*= 乘以AND赋值运算符,它将右操作数与左操作数相乘,并将结果赋值给左操作数 C * = A等于C = C * A.
/= 除法AND赋值运算符,它将左操作数除以右操作数,并将结果赋值给左操作数 C/= A相当于C = C/A.
%= 模数AND赋值运算符,使用两个操作数获取模数,并将结果赋给左操作数 C%= A等于C = C%A
<<= 左移AND赋值运算符 C << = 2与C = C << 2相同
>>= 右移AND赋值运算符 C >> = 2与C = C >> 2相同
&= 按位AND赋值运算符 C&= 2与C = C&2相同
^= 按位异或和赋值运算符 C ^ = 2与C = C ^ 2相同
|= 按位包含OR和赋值运算符 C | = 2与C = C |相同 2

运算符在Scala中的优先级

运算符优先级确定表达式中的术语分组。 这会影响表达式的计算方式。 某些运算符的优先级高于其他运算符; 例如,乘法运算符的优先级高于加法运算符 -

例如,x = 7 + 3 * 2; 这里,x被赋值为13,而不是20,因为operator *的优先级高于+,所以它首先乘以3 * 2然后加到7中。

看看下表。 优先级最高的运算符显示在表的顶部,优先级最低的运算符显示在底部。 在表达式中,将首先评估更高优先级的运算符。

类别 操作者 关联性
Postfix ()[] 左到右
Unary ! 〜 右到左
Multiplicative * /% 左到右
Additive + - 左到右
Shift >> >>> << 左到右
Relational >> = << = 左到右
Equality ==!= 左到右
Bitwise AND& 左到右
Bitwise XOR ^ 左到右
Bitwise OR | 左到右
Logical AND && 左到右
Logical OR || 左到右
Assignment = + = - = * =/=%= >> = << =&= ^ = | = 右到左
Comma, 左到右

Scala - IF ELSE Statements

本章将指导您完成Scala编程中的条件构造语句。 以下是在大多数编程语言中发现IF ... ELSE结构的典型决策的一般形式。

流程图 (Flow Chart)

以下是条件语句的流程图。

Scala IF ... ELSE结构

如果声明

'if'语句由一个布尔表达式后跟一个或多个语句组成。

语法 (Syntax)

'if'语句的语法如下。

if(Boolean_expression) {
   // Statements will execute if the Boolean expression is true
}

如果布尔表达式的计算结果为true,那么将执行'if'表达式中的代码块。 如果没有,将执行'if'表达式结束后(在结束大括号之后)的第一组代码。

尝试使用以下示例程序来理解Scala编程语言中的条件表达式(如果表达式)。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      var x = 10;
      if( x < 20 ){
         println("This is if statement");
      }
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

This is if statement

If-else 语句

'if'语句后面可以跟一个可选的else语句,该语句在布尔表达式为false时执行。

语法 (Syntax)

if ... else的语法是 -

if(Boolean_expression){
   //Executes when the Boolean expression is true
} else{
   //Executes when the Boolean expression is false
}

尝试使用以下示例程序来理解Scala编程语言中的条件语句(if- else语句)。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      var x = 30;
      if( x < 20 ){
         println("This is if statement");
      } else {
         println("This is else statement");
      }
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

This is else statement

If-else-if-else 语句

'if'语句后面可以跟一个可选的' else if...else '语句,这对于使用单个if ... else if语句测试各种条件非常有用。

当使用if,else if,else语句时,要记住几点。

  • 一个'if'可以有零个或一个其他的,它必须在任何其他if之后。

  • 一个'if'如果有的话可以有零到多个,并且它们必须在else之前。

  • 一旦其他成功,如果其他人或其他人将被测试,他将不会留下其他人。

语法 (Syntax)

以下是'if ... else if ... else'的语法如下 -

if(Boolean_expression 1){
   //Executes when the Boolean expression 1 is true
} else if(Boolean_expression 2){
   //Executes when the Boolean expression 2 is true
} else if(Boolean_expression 3){
   //Executes when the Boolean expression 3 is true
} else {
   //Executes when the none of the above condition is true.
}

尝试使用以下示例程序来理解Scala编程语言中的条件语句(if- else- if- else语句)。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      var x = 30;
      if( x == 10 ){
         println("Value of X is 10");
      } else if( x == 20 ){
         println("Value of X is 20");
      } else if( x == 30 ){
         println("Value of X is 30");
      } else{
         println("This is else statement");
      }
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Value of X is 30

Nested if-else 语句

嵌套if-else语句总是合法的,这意味着你可以在另一个ifelse-if语句中使用一个ifelse-if语句。

语法 (Syntax)

嵌套if-else的语法如下 -

if(Boolean_expression 1){
   //Executes when the Boolean expression 1 is true
   if(Boolean_expression 2){
      //Executes when the Boolean expression 2 is true
   }
}

尝试使用以下示例程序来理解Scala编程语言中的条件语句(nested-if语句)。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      var x = 30;
      var y = 10;
      if( x == 30 ){
         if( y == 10 ){
            println("X = 30 and Y = 10");
         }
      }
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

X = 30 and Y = 10

Scala - Loop Statements

本章将指导您完成Scala编程语言中的循环控制结构。

当您需要多次执行代码块时,可能会出现这种情况。 通常,语句按顺序执行:首先执行函数中的第一个语句,然后执行第二个语句,依此类推。

编程语言提供各种控制结构,允许更复杂的执行路径。

循环语句允许我们多次执行语句或语句组,以下是大多数编程语言中循环语句的一般形式 -

流程图 (Flow Chart)

循环架构

Scala编程语言提供以下类型的循环来处理循环需求。 单击表中的以下链接以检查其详细信息。

Sr.No 循环类型和描述
1

while loop

在给定条件为真时重复语句或语句组。 它在执行循环体之前测试条件。

2

do-while loop

像while语句一样,除了它测试循环体末尾的条件。

3

for loop

多次执行一系列语句,并缩写管理循环变量的代码。

循环控制语句 (Loop Control Statements)

循环控制语句将执行从其正常序列更改。 当执行离开作用域时,将销毁在该作用域中创建的所有自动对象。 因此,Scala不支持像Java那样的breakcontinue语句,但是从Scala 2.8开始,有一种方法可以打破循环。 单击以下链接以检查详细信息。

Sr.No 控制声明和描述
1

break statement

终止loop语句并将执行转移到loop语句。

无限循环

如果条件永远不会变为假,则循环变为无限循环。 如果您使用的是Scala,则while循环是实现无限循环的最佳方式。

以下程序实现无限循环。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      var a = 10;
      // An infinite loop.
      while( true ){
         println( "Value of a: " + a );
      }
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

如果您将执行上面的代码,它将进入无限循环,您可以通过按Ctrl + C键终止。

Value of a: 10
Value of a: 10
Value of a: 10
Value of a: 10
…………….

Scala - 函数

函数是执行任务的一组语句。 您可以将代码划分为单独的函数。 如何在不同的函数之间划分代码取决于您,但从逻辑上讲,除法通常是每个函数执行特定任务。

Scala既有函数又有方法,我们使用术语方法和函数可以互换,只有细微差别。 Scala方法是类的一部分,它具有名称,签名,可选的一些注释和一些字节码,其中Scala中的函数是可以分配给变量的完整对象。 换句话说,被定义为某个对象的成员的函数称为方法。

函数定义可以出现在源文件中的任何位置,Scala允许嵌套函数定义,即其他函数定义中的函数定义。 最重要的一点是,Scala函数的名称可以包含+,++,〜,&, - , - ,\,/,等等字符。

函数声明 (Function Declarations)

Scala函数声明具有以下形式 -

def functionName ([list of parameters]) : [return type]

如果不使用等号和方法体,则隐式声明方法为abstract

功能定义

Scala函数定义具有以下形式 -

语法 (Syntax)

def functionName ([list of parameters]) : [return type] = {
   function body
   return [expr]
}

这里, return type可以是任何有效的Scala数据类型list of parameters将是由逗号分隔的变量列表,参数列表和返回类型是可选的。 与Java非常相似, return语句可以与表达式一起使用,以防函数返回值。 以下是将添加两个整数并返回其总和的函数 -

语法 (Syntax)

object add {
   def addInt( a:Int, b:Int ) : Int = {
      var sum:Int = 0
      sum = a + b
      return sum
   }
}

一个不返回任何东西的函数可以返回一个相当于Java中的voidUnit ,并指示该函数不返回任何内容。 在Scala中没有返回任何内容的函数,它们被称为过程。

语法 (Syntax)

这是语法 -

object Hello{
   def printMe( ) : Unit = {
      println("Hello, Scala!")
   }
}

Calling 函数

Scala为调用方法提供了许多语法变体。 以下是调用方法的标准方法 -

functionName( list of parameters )

如果使用对象的实例调用函数,那么我们将使用类似于Java的点符号,如下所示 -

[instance.]functionName( list of parameters )

尝试以下示例程序来定义然后调用相同的函数。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      println( "Returned Value : " + addInt(5,7) );
   }
   def addInt( a:Int, b:Int ) : Int = {
      var sum:Int = 0
      sum = a + b
      return sum
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Returned Value : 12

Scala函数是Scala编程的核心,这也是Scala被假定为函数式编程语言的原因。 以下是与Scala函数相关的一些重要概念,Scala程序员应该理解这些概念。

函数Call-by-Name 具有命名参数的函数
具有变量参数的函数 递归函数
默认参数值 高阶函数
嵌套函数 匿名函数
Partially Applied Functions Currying功能

Scala - Closures

closure是一个函数,其返回值取决于在此函数外声明的一个或多个变量的值。

下面的一段代码带有匿名功能。

val multiplier = (i:Int) => i * 10

这里函数体中使用的唯一变量i * 10是i,它被定义为函数的参数。 请尝试以下代码 -

val multiplier = (i:Int) => i * factor

乘数中有两个自由变量: ifactor 。 其中之一,i,是函数的形式参数。 因此,每次调用乘数时都会绑定一个新值。 但是, factor不是一个正式的参数,那么这是什么? 让我们再添加一行代码。

var factor = 3
val multiplier = (i:Int) => i * factor

现在factor有一个对函数外部变量的引用,但是在封闭范围内。 该函数引用factor并每次读取其当前值。 如果一个函数没有外部引用,那么它本身就会被忽略。 无需外部环境。

请尝试以下示例程序。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      println( "multiplier(1) value = " +  multiplier(1) )
      println( "multiplier(2) value = " +  multiplier(2) )
   }
   var factor = 3
   val multiplier = (i:Int) => i * factor
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

multiplier(1) value = 3
multiplier(2) value = 6

Scala - Strings

本章将向您介绍Scala字符串。 在Scala中,与Java一样,字符串是不可变对象,即无法修改的对象。 另一方面,可以修改的对象(如数组)称为可变对象。 字符串是非常有用的对象,在本节的其余部分中,我们提供了java.lang.String类的重要方法。

创建一个字符串

以下代码可用于创建字符串 -

var greeting = "Hello world!";
or
var greeting:String = "Hello world!";

每当编译器在代码中遇到字符串文字时,它就会创建一个带有其值的String对象,在本例中为“Hello world!”。 String关键字也可以在备用声明中给出,如上所示。

请尝试以下示例程序。

例子 (Example)

object Demo {
   val greeting: String = "Hello, world!"
   def main(args: Array[String]) {
      println( greeting )
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Hello, world!

如前所述,String类是不可变的。 创建的字符串对象无法更改。 如果有必要对字符串进行大量修改,请使用Scala中提供的String Builder类。

String Length

用于获取对象信息的方法称为访问器方法。 可以与字符串一起使用的一种访问器方法是length()方法,它返回字符串对象中包含的字符数。

使用以下代码段来查找字符串的长度 -

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      var palindrome = "Dot saw I was Tod";
      var len = palindrome.length();
      println( "String Length is : " + len );
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

String Length is : 17

连接字符串

String类包括一个连接两个字符串的方法 -

string1.concat(string2);

这将返回一个新的字符串,该字符串为string1,并在结尾处添加了string2。 你也可以使用带有字符串文字的concat()方法,如 -

"My name is ".concat("Zara");

字符串通常与+运算符连接,如 -

"Hello," + " world" + "!"

结果如下 -

"Hello, world!"

以下代码行查找字符串长度。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      var str1 = "Dot saw I was ";
      var str2 =  "Tod";
      println("Dot " + str1 + str2);
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Dot Dot saw I was Tod

创建格式字符串

你有printf()和format()方法来打印格式化数字的输出。 String类有一个等效的类方法format(),它返回一个String对象而不是一个PrintStream对象。

尝试以下示例程序,它使用printf()方法 -

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      var floatVar = 12.456
      var intVar = 2000
      var stringVar = "Hello, Scala!"
      var fs = printf("The value of the float variable is " + "%f, while the value of the integer " + "variable is %d, and the string" + "is %s", floatVar, intVar, stringVar);
      println(fs)
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

命令

\>scalac Demo.scala
\>scala Demo

输出 (Output)

The value of the float variable is 12.456000, 
while the value of the integer variable is 2000, 
and the string is Hello, Scala!()

字符串插值

String Interpolation是在Scala编程语言中创建字符串的新方法。 此功能支持Scala-2.10及更高版本。 字符串插值:直接在进程字符串文字中嵌入变量引用的机制。

String Interpolation中有三种类型(插值器)实现。

's'字符串插值器

文字's'允许在处理字符串时直接使用变量,当你将's'添加到它时。 任何String变量,其范围可以在String中使用。 以下是's'字符串插值器的不同用法。

下面的示例代码片段用于实现's'插值器,将String变量($ name)附加到println语句中的普通String(Hello)。

val name = “James”
println(s “Hello, $name”) //output: Hello, James

字符串插值器也可以处理任意表达式。 以下代码片段用于使用's'字符串插值器处理具有任意表达式($ {1 + 1})的字符串(1 + 1)。 任何表达都可以嵌入'$ {}'中。

println(s “1 + 1 = ${1 + 1}”) //output: 1 + 1 = 2

尝试以下实现's'插值器的示例程序。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      val name = "James"
      println(s"Hello, $name")
      println(s"1 + 1 = ${1 + 1}")
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Hello, James
1 + 1 = 2

'f'插值器

文字'f'插值器允许创建格式化的字符串,类似于C语言中的printf。 使用'f'插值器时,所有变量引用都应该跟printf样式格式说明符,如%d,%i,%f等。

让我们举一个附加浮点值(height = 1.9d)和String变量(name =“James”)和普通字符串的例子。 以下是实现'f'插值器的代码片段。 这里$ name%s打印(String变量)James和$ height%2.2f打印(浮点值)1.90。

val height = 1.9d
val name = "James"
println(f"$name%s is $height%2.2f meters tall") //James is 1.90 meters tall

它是类型安全的(即)变量引用和后续格式说明符应匹配,否则显示错误。 'f'插值器使用Java中可用的String格式实用程序(格式说明符)。 默认情况下,变量引用后没有%字符。 它将假定为%s(字符串)。

'原始'插值器

'raw'插值器类似于's'插值器,除了它不执行字符串中文字的转义。 表中的以下代码片段将区分's'和'raw'插值器的用法。 在's'使用'\ n'效果的输出作为新行和'原始'用法的输出中,'\ n'将不起作用。 它将打印带有转义字母的完整字符串。

''插值器用法 '原始'插值器用法

Program -

object Demo {
   def main(args: Array[String]) {
      println(s"Result = \n a \n b")
   }
}

Program -

object Demo {
   def main(args: Array[String]) {
      println(raw"Result = \n a \n b")
   }
}

Output -

Result =
a
b

Output -

Result = \n a \n b

字符串的方法 (String Methods)

以下是java.lang.String类定义的方法列表,可以直接在Scala程序中使用 -

Sr.No 带描述的方法
1

char charAt(int index)

返回指定索引处的字符。

2

int compareTo(Object o)

将此String与另一个Object进行比较。

3

int compareTo(String anotherString)

按字典顺序比较两个字符串。

4

int compareToIgnoreCase(String str)

按字典顺序比较两个字符串,忽略大小写差异。

5

String concat(String str)

将指定的字符串连接到此字符串的末尾。

6

boolean contentEquals(StringBuffer sb)

当且仅当此String表示与指定的StringBuffer相同的字符序列时,返回true。

7

static String copyValueOf(char[] data)

返回表示指定数组中字符序列的String。

8

static String copyValueOf(char[] data, int offset, int count)

返回表示指定数组中字符序列的String。

9

boolean endsWith(String suffix)

测试此字符串是否以指定的后缀结尾。

10

boolean equals(Object anObject)

将此字符串与指定的对象进行比较。

11

boolean equalsIgnoreCase(String anotherString)

将此String与另一个String进行比较,忽略大小写。

12

byte getBytes()

使用平台的默认字符集将此String编码为字节序列,并将结果存储到新的字节数组中。

13

byte[] getBytes(String charsetName)

使用指定的字符集将此String编码为字节序列,将结果存储到新的字节数组中。

14

void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

将此字符串中的字符复制到目标字符数组中。

15

int hashCode()

返回此字符串的哈希码。

16

int indexOf(int ch)

返回指定字符第一次出现的字符串中的索引。

17

int indexOf(int ch, int fromIndex)

返回指定字符第一次出现的此字符串中的索引,从指定索引处开始搜索。

18

int indexOf(String str)

返回指定子字符串第一次出现的字符串中的索引。

19

int indexOf(String str, int fromIndex)

从指定的索引处开始,返回指定子字符串第一次出现的字符串中的索引。

20

String intern()

返回字符串对象的规范表示。

21

int lastIndexOf(int ch)

返回指定字符最后一次出现的字符串中的索引。

22

int lastIndexOf(int ch, int fromIndex)

返回指定字符最后一次出现的字符串中的索引,从指定的索引开始向后搜索。

23

int lastIndexOf(String str)

返回指定子字符串最右边出现的字符串中的索引。

24

int lastIndexOf(String str, int fromIndex)

返回指定子字符串最后一次出现的字符串中的索引,从指定索引开始向后搜索。

25

int length()

返回此字符串的长度。

26

boolean matches(String regex)

判断此字符串是否与给定的正则表达式匹配。

27

boolean regionMatches(boolean ignoreCase, int toffset, String other, int offset, int len)

测试两个字符串区域是否相等。

28

boolean regionMatches(int toffset, String other, int offset, int len)

测试两个字符串区域是否相等。

29

String replace(char oldChar , char newChar)

返回一个新字符串,该字符串是使用newChar替换此字符串中出现的所有oldChar。

30

String replaceAll(String regex, String replacement

将给定替换的给定正则表达式匹配的此字符串的每个子字符串替换。

31

String replaceFirst(String regex, String replacement)

将给定替换的给定正则表达式匹配的此字符串的第一个子字符串替换。

32

String[] split(String regex)

将此字符串拆分为给定正则表达式的匹配项。

33

String[] split(String regex, int limit)

将此字符串拆分为给定正则表达式的匹配项。

34

boolean startsWith(String prefix)

测试此字符串是否以指定的前缀开头。

35

boolean startsWith(String prefix, int toffset)

测试此字符串是否以指定的前缀开始指定的索引。

36

CharSequence subSequence(int beginIndex, int endIndex)

返回一个新的字符序列,它是该序列的子序列。

37

String substring(int beginIndex)

返回一个新字符串,该字符串是此字符串的子字符串。

38

String substring(int beginIndex, int endIndex)

返回一个新字符串,该字符串是此字符串的子字符串。

39

char[] toCharArray()

将此字符串转换为新的字符数组。

40

String toLowerCase()

使用默认语言环境的规则将此String中的所有字符转换为小写。

41

String toLowerCase(Locale locale)

使用给定Locale的规则将此String中的所有字符转换为小写。

42

String toString()

这个对象(已经是一个字符串!)本身就返回了。

43

String toUpperCase()

使用默认语言环境的规则将此String中的所有字符转换为大写。

44

String toUpperCase(Locale locale)

使用给定Locale的规则将此String中的所有字符转换为大写。

45

String trim()

返回字符串的副本,省略前导和尾随空格。

46

static String valueOf(primitive data type x)

返回传递的数据类型参数的字符串表示形式。

Scala - Arrays

Scala提供了一个数据结构,即array ,它存储了相同类型元素的固定大小顺序集合。 数组用于存储数据集合,但将数组视为相同类型的变量集合通常更有用。

您可以声明一个数组变量(例如数字)并使用数字[0],数字[1]和...,数字[99]来表示单个变量,例如number0,number1,...和number99,而不是声明单个变量。个别变数。 本教程介绍如何使用索引变量声明数组变量,创建数组和处理数组。 数组的第一个元素的索引是数字零,最后一个元素的索引是元素的总数减1。

声明数组变量

要在程序中使用数组,必须声明一个变量以引用该数组,并且必须指定该变量可以引用的数组类型。

以下是声明数组变量的语法。

语法 (Syntax)

var z:Array[String] = new Array[String](3)
or
var z = new Array[String](3)

这里,z被声明为一个字符串数组,最多可包含三个元素。 可以将值分配给单个元素或访问单个元素,可以使用以下命令来完成 -

Command

z(0) = "Zara"; z(1) = "Nuha"; z(4/2) = "Ayan"

这里,最后一个例子表明,索引通常可以是产生整数的任何表达式。 还有一种定义数组的方法 -

var z = Array("Zara", "Nuha", "Ayan")

下图代表一个数组myList 。 这里, myList包含十个double值,索引从0到9。

Scala数组

处理数组

处理数组元素时,我们经常使用循环控制结构,因为数组中的所有元素都是相同的类型,并且数组的大小是已知的。

下面是一个示例程序,展示如何创建,初始化和处理数组 -

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      var myList = Array(1.9, 2.9, 3.4, 3.5)
      // Print all the array elements
      for ( x <- myList ) {
         println( x )
      }
      // Summing all elements
      var total = 0.0;
      for ( i <- 0 to (myList.length - 1)) {
         total += myList(i);
      }
      println("Total is " + total);
      // Finding the largest element
      var max = myList(0);
      for ( i <- 1 to (myList.length - 1) ) {
         if (myList(i) > max) max = myList(i);
      }
      println("Max is " + max);
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

1.9
2.9
3.4
3.5
Total is 11.7
Max is 3.5

Scala不直接支持各种数组操作,并提供各种方法来处理任何维度的数组。 如果要使用不同的方法,则需要导入Array._包。

多维数组

在许多情况下,您需要定义和使用多维数组(即,元素为数组的数组)。 例如,矩阵和表是可以实现为二维阵列的结构的示例。

以下是定义二维数组的示例 -

var myMatrix = ofDim[Int](3,3)

这是一个包含三个元素的数组,每个元素都是一个包含三个元素的整数数组。

尝试以下示例程序来处理多维数组 -

例子 (Example)

import Array._
object Demo {
   def main(args: Array[String]) {
      var myMatrix = ofDim[Int](3,3)
      // build a matrix
      for (i <- 0 to 2) {
         for ( j <- 0 to 2) {
            myMatrix(i)(j) = j;
         }
      }
      // Print two dimensional array
      for (i <- 0 to 2) {
         for ( j <- 0 to 2) {
            print(" " + myMatrix(i)(j));
         }
         println();
      }
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

0 1 2
0 1 2
0 1 2

连接数组

尝试以下示例,该示例使用concat()方法来连接两个数组。 您可以将多个数组作为参数传递给concat()方法。

例子 (Example)

import Array._
object Demo {
   def main(args: Array[String]) {
      var myList1 = Array(1.9, 2.9, 3.4, 3.5)
      var myList2 = Array(8.9, 7.9, 0.4, 1.5)
      var myList3 =  concat( myList1, myList2)
      // Print all the array elements
      for ( x <- myList3 ) {
         println( x )
      }
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

1.9
2.9
3.4
3.5
8.9
7.9
0.4
1.5

创建带范围的数组

使用range()方法生成一个数组,该数组包含给定范围内递增整数的序列。 您可以使用final参数作为步骤来创建序列; 如果你不使用final参数,那么step将被假定为1。

让我们举一个创建范围数组(10,20,2)的例子:它意味着创建一个数组在10到20之间且范围不同的数组2.数组中的元素是10,12,14,16和18 。

另一个例子:范围(10,20)。 这里没有给出范围差异,所以默认情况下它假定为1个元素。 它创建一个数组,其元素在10到20之间,范围不同1.数组中的元素是10,11,12,13,...和19。

以下示例程序显示如何创建带范围的数组。

例子 (Example)

import Array._
object Demo {
   def main(args: Array[String]) {
      var myList1 = range(10, 20, 2)
      var myList2 = range(10,20)
      // Print all the array elements
      for ( x <- myList1 ) {
         print( " " + x )
      }
      println()
      for ( x <- myList2 ) {
         print( " " + x )
      }
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

10 12 14 16 18
10 11 12 13 14 15 16 17 18 19

Scala数组方法

以下是重要的方法,您可以在使用数组时使用它们。 如上所示,您必须在使用任何提到的方法之前导入Array._包。 有关可用方法的完整列表,请查看Scala的官方文档。

Sr.No 带描述的方法
1

def apply( x: T, xs: T* ): Array[T]

创建一个T对象数组,其中T可以是Unit,Double,Float,Long,Int,Char,Short,Byte,Boolean。

2

def concat[T]( xss: Array[T]* ): Array[T]

将所有数组连接成一个数组。

3

def copy( src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int ): Unit

将一个数组复制到另一个。 相当于Java的System.arraycopy(src,srcPos,dest,destPos,length)。

4

def empty[T]: Array[T]

返回长度为0的数组

5

def iterate[T]( start: T, len: Int )( f: (T) =》 T ): Array[T]

返回一个包含函数重复应用程序的数组到起始值。

6

def fill[T]( n: Int )(elem: =》 T): Array[T]

返回一个数组,其中包含多次元素计算的结果。

7

def fill[T]( n1: Int, n2: Int )( elem: =》 T ): Array[Array[T]]

返回一个二维数组,其中包含多次元素计算的结果。

8

def iterate[T]( start: T, len: Int)( f: (T) =》 T ): Array[T]

返回一个包含函数重复应用程序的数组到起始值。

9

def ofDim[T]( n1: Int ): Array[T]

创建具有给定尺寸的数组。

10

def ofDim[T]( n1: Int, n2: Int ): Array[Array[T]]

创建一个二维数组

11

def ofDim[T]( n1: Int, n2: Int, n3: Int ): Array[Array[Array[T]]]

创建一个三维数组

12

def range( start: Int, end: Int, step: Int ): Array[Int]

返回在某个整数间隔中包含等间距值的数组。

13

def range( start: Int, end: Int ): Array[Int]

返回一个数组,其中包含范围中递增整数的序列。

14

def tabulate[T]( n: Int )(f: (Int)=》 T): Array[T]

返回一个数组,该数组包含从0开始的整数值范围内的给定函数的值。

15

def tabulate[T]( n1: Int, n2: Int )( f: (Int, Int ) =》 T): Array[Array[T]]

返回一个二维数组,其中包含从0开始的整数值范围内给定函数的值。

Scala - Collections

Scala拥有丰富的集合库。 集合是事物的容器。 这些容器可以是有序的,线性的项目集合,例如List,Tuple,Option,Map等。集合可以具有任意数量的元素或者被限制为零或一个元素(例如,Option)。

收藏可能是strictlazy 。 延迟集合包含的元素在访问之前可能不会消耗内存,例如Ranges 。 另外,集合可能是mutable (引用的内容可以改变)或immutable (引用引用的东西永远不会改变)。 请注意,不可变集合可能包含可变项。

对于某些问题,可变集合更好地工作,而对于其他集合,不可变集合更好地工作。 如果有疑问,最好从不可变集合开始,如果需要可变集合,则稍后更改。

本章将介绍最常用的集合类型以及这些集合上最常用的操作。

Sr.No 带描述的集合
1

Scala Lists

Scala的List [T]是T类型的链表。

2

Scala Sets

集合是同一类型的成对不同元素的集合。

3

Scala Maps

Map是键/值对的集合。 可以根据其键检索任何值。

4

Scala Tuples

与数组或列表不同,元组可以保存具有不同类型的对象。

5

Scala Options

Option [T]为给定类型的零个或一个元素提供容器。

6

Scala Iterators

迭代器不是集合,而是逐个访问集合元素的方法。

Scala - Traits

特征封装了方法和字段定义,然后可以通过将它们混合到类中来重用它们。 与类继承不同,其中每个类必须仅从一个超类继承,类可以混合任意数量的特征。

Traits用于通过指定支持的方法的签名来定义对象类型。 Scala还允许部分实现特征,但特征可能没有构造函数参数。

特征定义看起来就像一个类定义,除了它使用关键字trait 。 以下是特质的基本示例语法。

语法 (Syntax)

trait Equal {
   def isEqual(x: Any): Boolean
   def isNotEqual(x: Any): Boolean = !isEqual(x)
}

该特征由两个方法isEqualisNotEqual 。 在这里,我们没有给出isEqual的任何实现,而另一种方法有其实现。 扩展特征的子类可以为未实现的方法提供实现。 所以特征与Java中的abstract classes非常相似。

让我们假设一个特征的例子Equal包含两个方法isEqual()isNotEqual() 。 特性Equal包含一个isEqual()实现方法,因此当用户定义的类Point扩展特性Equal ,应该提供Point类中的isEqual()方法的实现。

这里需要知道Scala的两个重要方法,它们在下面的例子中使用。

  • obj.isInstanceOf [Point]要检查obj的类型和Point是否相同。

  • obj.asInstanceOf [Point]表示通过获取对象obj类型并返回与Point类型相同的obj来精确转换。

尝试以下示例程序来实现特征。

例子 (Example)

trait Equal {
   def isEqual(x: Any): Boolean
   def isNotEqual(x: Any): Boolean = !isEqual(x)
}
class Point(xc: Int, yc: Int) extends Equal {
   var x: Int = xc
   var y: Int = yc
   def isEqual(obj: Any) = obj.isInstanceOf[Point] && obj.asInstanceOf[Point].x == y
}
object Demo {
   def main(args: Array[String]) {
      val p1 = new Point(2, 3)
      val p2 = new Point(2, 4)
      val p3 = new Point(3, 3)
      println(p1.isNotEqual(p2))
      println(p1.isNotEqual(p3))
      println(p1.isNotEqual(2))
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

true
false
true

价值类和通用特征

值类是Scala中的新机制,以避免分配运行时对象。 它包含一个只有一个val参数的主构造函数。 它仅包含方法(def),不允许使用var,val,嵌套类,特征或对象。 值类不能由另一个类扩展。 这可以通过使用AnyVal扩展您的值类来实现。 自定义数据类型的类型安全性,没有运行时开销。

让我们举一个值类,权重,高度,电子邮件,年龄等的示例。对于所有这些示例,不需要在应用程序中分配内存。

值类不允许扩展特征。 为了允许值类扩展特征,引入了针对Any扩展的universal traits

例子 (Example)

trait Printable extends Any {
   def print(): Unit = println(this)
}
class Wrapper(val underlying: Int) extends AnyVal with Printable
object Demo {
   def main(args: Array[String]) {
      val w = new Wrapper(3)
      w.print() // actually requires instantiating a Wrapper instance
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

它将为您提供Wrapper类的哈希码。

Wrapper@13

何时使用特征?

没有确定的规则,但这里有一些指导方针需要考虑 -

  • 如果不再重用该行为,那么将其作为具体类。 毕竟,这不是可重用的行为。

  • 如果它可以在多个不相关的类中重用,那么将其作为特征。 只有特征可以混合到类层次结构的不同部分。

  • 如果要在Java代码中inherit它,请使用抽象类。

  • 如果您计划以编译形式分发它,并且您希望外部组编写从其继承的类,您可能倾向于使用抽象类。

  • 如果效率非常重要,那就倾向于使用一门课程。

Scala - Pattern Matching

在函数值和闭包之后,模式匹配是Scala中使用次数最多的第二个特性。 Scala在处理消息时为模式匹配提供了很好的支持。

模式匹配包括一系列备选方案,每个备选方案都以关键字case开头。 每个替代方案都包括一个pattern和一个或多个expressions ,如果模式匹配,将对其进行评估。 箭头符号=“将模式与表达式分开。

请尝试以下示例程序,该程序显示如何匹配整数值。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      println(matchTest(3))
   }
   def matchTest(x: Int): String = x match {
      case 1 => "one"
      case 2 => "two"
      case _ => "many"
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

many

带有case语句的块定义了一个函数,它将整数映射到字符串。 match关键字提供了一种将函数(如上面的模式匹配函数)应用于对象的便捷方法。

尝试以下示例程序,该程序将值与不同类型的模式进行匹配。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      println(matchTest("two"))
      println(matchTest("test"))
      println(matchTest(1))
   }
   def matchTest(x: Any): Any = x match {
      case 1 => "one"
      case "two" => 2
      case y: Int => "scala.Int"
      case _ => "many"
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

2
many
one

使用Case Classes进行匹配

case classes是特殊类,用于与案例表达式进行模式匹配。 从语法上讲,这些是带有特殊修饰符的标准类: case

尝试以下,它是一个使用case类的简单模式匹配示例。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      val alice = new Person("Alice", 25)
      val bob = new Person("Bob", 32)
      val charlie = new Person("Charlie", 32)
      for (person <- List(alice, bob, charlie)) {
         person match {
            case Person("Alice", 25) => println("Hi Alice!")
            case Person("Bob", 32) => println("Hi Bob!")
            case Person(name, age) => println(
               "Age: " + age + " year, name: " + name + "?")
         }
      }
   }
   case class Person(name: String, age: Int)
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Hi Alice!
Hi Bob!
Age: 32 year, name: Charlie?

添加case关键字会使编译器自动添加许多有用的功能。 关键字建议在模式匹配中与案例表达式关联。

首先,编译器自动将构造函数参数转换为不可变字段(vals)。 val关键字是可选的。 如果需要可变字段,请使用var关键字。 因此,我们的构造函数参数列表现在更短。

其次,编译器自动为类生成equals, hashCode,toString方法,该方法使用指定为构造函数参数的字段。 因此,我们不再需要自己的toString()方法。

最后, Person类的主体也变空了,因为没有我们需要定义的方法!

Scala - Regular Expressions

本章介绍Scala如何通过scala.util.matching包中提供的Regex类支持正则表达式。

尝试以下示例程序,我们将尝试从语句中找出Scala一词。

例子 (Example)

import scala.util.matching.Regex
object Demo {
   def main(args: Array[String]) {
      val pattern = "Scala".r
      val str = "Scala is Scalable and cool"
      println(pattern findFirstIn str)
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Some(Scala)

我们创建一个String并在其上调用r( )方法。 Scala隐式地将String转换为RichString并调用该方法来获取Regex的实例。 要查找正则表达式的第一个匹配项,只需调用findFirstIn()方法即可。 如果我们不想仅查找第一次出现的匹配单词,我们可以使用findAllIn( )方法,如果目标字符串中有多个Scala单词,则会返回所有匹配的集合话。

您可以使用mkString()方法来连接结果列表,您可以使用管道(|)来搜索Scala的小型和大写情况,您可以使用Regex构造函数或r()方法来创建模式。

请尝试以下示例程序。

例子 (Example)

import scala.util.matching.Regex
object Demo {
   def main(args: Array[String]) {
      val pattern = new Regex("(S|s)cala")
      val str = "Scala is scalable and cool"
      println((pattern findAllIn str).mkString(","))
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Scala,scala

如果您想替换匹配的文本,我们可以使用replaceFirstIn( )替换第一个匹配或replaceAllIn( )来替换所有匹配项。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      val pattern = "(S|s)cala".r
      val str = "Scala is scalable and cool"
      println(pattern replaceFirstIn(str, "Java"))
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Java is scalable and cool

形成正则表达式

Scala从Java继承了它的正则表达式语法,后者又继承了Perl的大部分功能。 这里只是一些应该足够复兴的例子 -

以下是列出Java中可用的所有正则表达式Meta字符语法的表。

子表达式 火柴
^ 匹配行首。
$ 匹配行尾。
. 匹配除换行符之外的任何单个字符。 使用m选项也可以匹配换行符。
[...] 匹配括号中的任何单个字符。
[^...] 匹配不在括号中的任何单个字符
\\A 整个字符串的开头
\\z 整个字符串的结尾
\\Z 除允许的最终行终止符之外的整个字符串的结尾。
re* 匹配前面表达式的0次或更多次出现。
re+ 匹配前一项中的一项或多项
re? 匹配前面表达式的0或1次出现。
re{ n} 准确匹配前面表达式的n个出现次数。
re {n,} 匹配前面表达式的n次或多次出现。
re {n,m} 匹配前面表达式的至少n次和最多m次出现。
a|b 匹配a或b。
(re) 对正则表达式进行分组并记住匹配的文本。
(?: 回覆) 将正则表达式分组而不记住匹配的文本。
(?> re) 匹配独立模式,无需回溯。
\\w 匹配单词字符。
\\W 匹配非单词字符。
\\s 匹配空白。 相当于[\ t\n\r\n]。
\\S 匹配非空白。
\\d 匹配数字。 相当于[0-9]。
\\D 匹配非数字。
\\A 匹配字符串的开头。
\\Z 匹配字符串的结尾。 如果存在换行符,则它在换行符之前匹配。
\\z 匹配字符串的结尾。
\\G 匹配指向上一场比赛结束的位置。
\\n 反向捕获组号“n”
\\b 在括号外匹配单词边界。 在括号内匹配退格(0x08)。
\\B 匹配非字边界。
\\n, \\t, etc. 匹配换行符,回车符,制表符等。
\\Q 逃脱(引用)所有字符到\\ E
\\E 结束引用以\\ Q开头

正则表达式示例

描述
. 匹配除换行符之外的任何字符
[Rr]uby 匹配“Ruby”或“ruby”
rub[ye] 匹配“红宝石”或“鲁布”
[aeiou] 匹配任何一个小写元音
[0-9] 匹配任何数字; 与[0123456789]相同
[a-z] 匹配任何小写ASCII字母
[A-Z] 匹配任何大写的ASCII字母
[a-zA-Z0-9] 匹配上述任何一项
[^aeiou] 匹配小写元音以外的任何内容
[^0-9] 匹配除数字之外的任何内容
\\d 匹配数字:[0-9]
\\D 匹配非数字:[^ 0-9]
\\s 匹配空白字符:[\ t\r\n\f]
\\S 匹配非空白:[^\t\r\n\f]
\\w 匹配单个字符:[A-Za-z0-9_]
\\W 匹配非单词字符:[^ A-Za-z0-9_]
ruby? 匹配“rub”或“ruby”:y是可选的
ruby* 匹配“rub”加0或更多ys
ruby+ 匹配“擦”加1或更多ys
\\d{3}Match exactly 3 digits
\\d{3,} 匹配3位或更多位数
\\d{3,5} 匹配3,4或5位数
\\D\\d+ 没有组:+重复\\ d
(\\D\\d)+/ 分组:+重复\\ D\d对
([Rr]uby(, )?)+ 匹配“Ruby”,“Ruby,ruby,ruby”等。

Note - 每个反斜杠在上面的字符串中出现两次。 这是因为在Java和Scala中,单个反斜杠是字符串文字中的转义字符,而不是字符串中显示的常规字符。 因此,不需要'\',而是需要编写'\\'以在字符串中获得单个反斜杠。

请尝试以下示例程序。

例子 (Example)

import scala.util.matching.Regex
object Demo {
   def main(args: Array[String]) {
      val pattern = new Regex("abl[ae]\\d+")
      val str = "ablaw is able1 and cool"
      println((pattern findAllIn str).mkString(","))
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

able1

Scala - Exception Handling

Scala的异常就像许多其他语言(如Java)中的异常一样。 方法可以通过抛出异常来终止,而不是以正常方式返回值。 但是,Scala实际上并没有检查异常。

当你想要处理异常时,你可以像在Java中一样使用try {...} catch {...}块,除了catch块使用匹配来识别和处理异常。

抛出异常

抛出异常与Java中的异常相同。 您创建一个异常对象,然后使用throw关键字抛出它,如下所示。

throw new IllegalArgumentException

捕捉异常

Scala允许您在单个块中try/catch任何异常,然后使用case块对其执行模式匹配。 尝试以下示例程序来处理异常。

例子 (Example)

import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
object Demo {
   def main(args: Array[String]) {
      try {
         val f = new FileReader("input.txt")
      } catch {
         case ex: FileNotFoundException =>{
            println("Missing file exception")
         }
         case ex: IOException => {
            println("IO Exception")
         }
      }
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Missing file exception

try-catch表达式的行为与其他具有异常的语言相同。 正文被执行,如果它抛出异常,则依次尝试每个catch子句。

最后的条款

如果要使某些代码执行而无论表达式如何终止,您可以使用finally子句包装表达式。 请尝试以下程序。

例子 (Example)

import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
object Demo {
   def main(args: Array[String]) {
      try {
         val f = new FileReader("input.txt")
      } catch {
         case ex: FileNotFoundException => {
            println("Missing file exception")
         }
         case ex: IOException => {
            println("IO Exception")
         }
      } finally {
         println("Exiting finally...")
      }
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Missing file exception
Exiting finally...

Scala - Extractors

Scala中的提取器是一个对象,它有一个名为unapply的方法作为其成员之一。 该unapply方法的目的是匹配一个值并将其分开。 通常,提取器对象还定义了apply构建值的双重方法,但这不是必需的。

例子 (Example)

让我们举一个对象定义applyunapply方法的例子。 apply方法具有与以往相同的含义:它将Test转换为可以应用于括号中的参数的对象,方法与应用方法相同。 所以你可以编写Test(“Zara”,“gmail.com”)来构造字符串“Zara@gmail.com”。

unapply方法是将Test类转换为extractor ,它反转了apply的构造过程。 如果apply需要两个字符串并形成一个电子邮件地址字符串,则unapply将获取一个电子邮件地址并返回两个字符串: user和地址domain

unapply还必须处理给定字符串不是电子邮件地址的情况。 这就是为什么unapply在字符串对上返回Option类型的原因。 如果字符串str是具有给定用户和域部分的电子邮件地址,则其结果是Some (user, domain) ;如果str不是电子邮件地址,则结果为None。 以下是一些示例。

语法 (Syntax)

unapply("Zara@gmail.com") equals Some("Zara", "gmail.com")
unapply("Zara Ali") equals None

以下示例程序显示了电子邮件地址的提取器对象。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      println ("Apply method : " + apply("Zara", "gmail.com"));
      println ("Unapply method : " + unapply("Zara@gmail.com"));
      println ("Unapply method : " + unapply("Zara Ali"));
   }
   // The injection method (optional)
   def apply(user: String, domain: String) = {
      user +"@"+ domain
   }
   // The extraction method (mandatory)
   def unapply(str: String): Option[(String, String)] = {
      val parts = str split "@"
      if (parts.length == 2){
         Some(parts(0), parts(1)) 
      } else {
         None
      }
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Apply method : Zara@gmail.com
Unapply method : Some((Zara,gmail.com))
Unapply method : None

与提取器匹配的模式

当类的实例后跟带有零个或多个参数列表的括号时,编译器apply在该实例上调用apply方法。 我们可以在对象和类中定义应用。

如上所述, unapply方法的目的是提取我们正在寻找的特定值。 它做相反的操作apply 。 使用match语句比较提取器对象时,将自动执行unapply方法。

请尝试以下示例程序。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      val x = Demo(5)
      println(x)
      x match {
         case Demo(num) => println(x+" is bigger two times than "+num)
         //unapply is invoked
         case _ => println("i cannot calculate")
      }
   }
   def apply(x: Int) = x*2
   def unapply(z: Int): Option[Int] = if (z%2==0) Some(z/2) else None
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

10
10 is bigger two times than 5

Scala - Files I/O

Scala是开放的,可以使用任何Java对象, java.io.File是可以在Scala编程中用于读写文件的对象之一。

以下是写入文件的示例程序。

例子 (Example)

import java.io._
object Demo {
   def main(args: Array[String]) {
      val writer = new PrintWriter(new File("test.txt" ))
      writer.write("Hello Scala")
      writer.close()
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

它将在当前目录中创建一个名为Demo.txt的文件,该文件放在该目录中。 以下是该文件的内容。

输出 (Output)

Hello Scala

从命令行读取一行

有时您需要从屏幕读取用户输入,然后继续进行进一步处理。 以下示例程序向您展示如何从命令行读取输入。

例子 (Example)

object Demo {
   def main(args: Array[String]) {
      print("Please enter your input : " )
      val line = Console.readLine
      println("Thanks, you just typed: " + line)
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Please enter your input : Scala is great
Thanks, you just typed: Scala is great

阅读文件内容

从文件中读取非常简单。 您可以使用Scala的Source类及其伴随对象来读取文件。 以下是向您展示如何从我们之前创建的"Demo.txt"文件中读取的示例。

例子 (Example)

import scala.io.Source
object Demo {
   def main(args: Array[String]) {
      println("Following is the content read:" )
      Source.fromFile("Demo.txt" ).foreach { 
         print 
      }
   }
}

将上述程序保存在Demo.scala 。 以下命令用于编译和执行此程序。

Command

\>scalac Demo.scala
\>scala Demo

输出 (Output)

Following is the content read:
Hello Scala
↑回到顶部↑
WIKI教程 @2018