Scala
第一章入门
0、为什么学Scala
Spark新一代内存及级大数据计算框架,是大数据的重要内容
Spark是适用Scala编写的。因此为了更好的学习Spark,需要掌握Scala这门语言
Spark的兴起,带动了Scala的发展
1、Scala和Java关系
Java运行原理
-先编译,再解释
- .java源文件--->编译器(javac)--->.class字节码文件--->JVM(java 不同平台)--->机器指令
Scala运行原理
-先编译,再解释
- .scala源文件--->编译器(scalac)--->.class字节码文件--->JVM(scala 不同平台)--->机器指令
2、Scala环境搭建
Scala环境搭建_asd623444055的博客-CSDN博客
3、HelloScala
(1)java编译过程
1)新建文件HelloJava.java
2)编写代码
public class HelloJava{
public static void main(String[] args) {
System.out.println("HelloJava");
}
}
3)使用编译器编写
4)生成字节码文件
5)执行字节码文件
(2)Scala编译过程
1)新建文件HelloScala.scala
2)编写代码
object HelloScala{
def main(args: Array[String]): Unit = {
println("HelloScala")
}
}
3)使用编译器编写
4)生成字节码文件
5)执行字节码文件
(3)使用java 编译Scala文件
Java不支持执行Scala命令
(4)使用Scala 编译Java文件(不建议)
Scala命令可以执行部分Java程序:兼容部分语法和代码。不建议
4、创建IDEA项目工程
1.引入Scala框架
2.创建Scala类
3.HelloIWorld
package com.scala.chapter01
/**
* 这是第一个HelloScala程序
*
* -object 名称
* 从语法角度讲,上面语法声明了一个伴生对象
* Scala是纯面向对象,去除了Java中的static语法,通过伴生对象来模拟static效果
*
*
* -伴生对象
* 伴随类产生的对象
* 当我们对源文件进行编译之后,默认会生成两个字节码文件,一个是伴生类,另一个是伴生对象所属类
* 其实真正的伴生对象是 伴生对象所属类中创建的单例对象
*
* 如果不想默认生成伴生类,可以手动生成,要求伴生类名称和伴生对象名称一致
*
* 注意:以后在Scala语言中,如果要定义类似Java的Static内容,都应该放到伴生对象中声明
*
* main方法名
* 小括号表示参数列表
* 参数声明方式:java -> 类型参数名
* scala-> 参数名:类型
* public修饰符:scala中没有public关键字,如果不声明访问权限,那么就是公共的
* static修饰符:scala中没有静态语法,所有没有static关键字
* void关键字:表示返回值,但是不遵循面向对象语法,所有scala中没有,但是有Unit类,表示没有返回值
* scala中:方法名(参数列表):返回值类型
* scala中声明方法必须采用关键字def声明
* scala中方法实现赋值给方法声明,所以中间需要等号连接
*
* Scala是一个完全面向对象的语言,所以没有静态语法,为了能调用静态语法(模仿静态语法),采用了伴生对象单例的方式调用方法
*
* >object
* 关键字,表示声明一个伴生对象
* >Scala01_HelloWorld
* 伴生对象的名字,取名的时候需要符合标识符命名规则
* >def
* 关键字 标识声明一个方法
* >main
* 方法的名称
* >(args: Array[String])
* &args 参数名称
* &Array[String]参数类型,在Scala语言中,[]表示泛型
* &声明参数的时候,名称在前,类型在后,名称和类型之间用冒号分隔
* >Unit
* &返回值类型为空,相当于java语言中的void关键字
* &Unit是一个类型,当前类型只有一个实例()
* &参数列表和返回值类型之间,用冒号进行分隔
* &返回值类型和函数体之间用等号进行连接
* > println("HelloScala")
* 向控制台打印输出内容
* 在Scala语言中,语句结束不需要加分号
* 伴生对象
* -从字面意思来讲,伴生对象就是伴随类产生的对象
* -在scala中,没有static关键字,通过伴生对象模拟static关键字的实现
* -当通过object名称定义一个伴生对象的时候,默认底层会编译生成两个字节码文件,一个是伴生类,
* 另一个是伴生对象所属类。实际我们所说的伴生对象是伴生对象所属类中定义的一个单例对象,然后
* 通过对象 .的方式访问属性或者方法等
*
* -以后在scala程序中,如果要想实现static效果,那么我们应该将属性以及方法定义在伴生对象中
*/
object Scala01_HelloWorld {
def main(args: Array[String]): Unit = {
println("HelloWorld")
}
}
//伴生对象
object Student{
var master:String = "John"
}
//伴生类
class Student{
var name:String = _
var age:Int = _
}
反编译
伴生对象所属类
package com.scala.chapter01;
import scala.reflect.ScalaSignature;
@ScalaSignature(bytes="\006\001!:Q!\001\002\t\002%\t!cU2bY\006\004\024g\030%fY2|wk\034:mI*\0211\001B\001\nG\"\f\007\017^3saER!!\002\004\002\013M\034\027\r\\1\013\003\035\t1aY8n\007\001\001\"AC\006\016\003\t1Q\001\004\002\t\0025\021!cU2bY\006\004\024g\030%fY2|wk\034:mIN\0211B\004\t\003\037Ei\021\001\005\006\002\013%\021!\003\005\002\007\003:L(+\0324\t\013QYA\021A\013\002\rqJg.\033;?)\005I\001\"B\f\f\t\003A\022\001B7bS:$\"!\007\017\021\005=Q\022BA\016\021\005\021)f.\033;\t\013u1\002\031\001\020\002\t\005\024xm\035\t\004\037}\t\023B\001\021\021\005\025\t%O]1z!\t\021SE\004\002\020G%\021A\005E\001\007!J,G-\0324\n\005\031:#AB*ue&twM\003\002%!\001")
public final class Scala01_HelloWorld
{
public static void main(String[] paramArrayOfString)
{
Scala01_HelloWorld..MODULE$.main(paramArrayOfString);
}
}
伴生类
package com.scala.chapter01;
import scala.Predef.;
public final class Scala01_HelloWorld$
{
public static final MODULE$;
static
{
new ();
}
public void main(String[] args)
{
Predef..MODULE$.println("HelloIDEAScala");
}
private Scala01_HelloWorld$() { MODULE$ = this; }
}
反编译
伴生对象所属类
package com.scala.chapter01;
public final class Student$
{
public static final MODULE$;
private String master;
static
{
new ();
}
public String master()
{
return this.master; }
public void master_$eq(String x$1) { this.master = x$1; }
private Student$()
{
MODULE$ = this;
this.master = "John";
}
}
伴生类
package com.scala.chapter01;
import scala.reflect.ScalaSignature;
@ScalaSignature(bytes="\006\001\r;Q!\001\002\t\002%\tqa\025;vI\026tGO\003\002\004\t\005I1\r[1qi\026\024\b'\r\006\003\013\031\tQa]2bY\006T\021aB\001\004G>l7\001\001\t\003\025-i\021A\001\004\006\031\tA\t!\004\002\b'R,H-\0328u'\tYa\002\005\002\020#5\t\001CC\001\006\023\t\021\002C\001\004B]f\024VM\032\005\006)-!\t!F\001\007y%t\027\016\036 \025\003%AqaF\006A\002\023\005\001$\001\004nCN$XM]\013\0023A\021!$\b\b\003\037mI!\001\b\t\002\rA\023X\rZ3g\023\tqrD\001\004TiJLgn\032\006\0039AAq!I\006A\002\023\005!%\001\006nCN$XM]0%KF$\"a\t\024\021\005=!\023BA\023\021\005\021)f.\033;\t\017\035\002\023\021!a\0013\005\031\001\020J\031\t\r%Z\001\025)\003\032\003\035i\027m\035;fe\0022A\001\004\002\001WM\021!F\004\005\006))\"\t!\f\013\002]A\021!B\013\005\na)\002\r\0211A\005\002a\tAA\\1nK\"I!G\013a\001\002\004%\taM\001\t]\006lWm\030\023fcR\0211\005\016\005\bOE\n\t\0211\001\032\021\0311$\006)Q\0053\005)a.Y7fA!I\001H\013a\001\002\004%\t!O\001\004C\036,W#\001\036\021\005=Y\024B\001\037\021\005\rIe\016\036\005\n})\002\r\0211A\005\002}\nq!Y4f?\022*\027\017\006\002$\001\"9q%PA\001\002\004Q\004B\002\"+A\003&!(\001\003bO\026\004\003")
public class Student
{
private String name;
private int age;
public static void master_$eq(String paramString)
{
Student..MODULE$.master_$eq(paramString);
}
public static String master()
{
return Student..MODULE$.master();
}
public String name()
{
return this.name; }
public void name_$eq(String x$1) { this.name = x$1; }
public int age() { return this.age; }
public void age_$eq(int x$1) { this.age = x$1; }
}
第2章 变量和数据类型
1、变量和常量
package com.scala.chapter02
/**
* 变量与常量
* Java
* --变量
* 数据类型 变量名 = 值
* int a = 10;
* --常量
* final 数据类型 变量名 = 值
* final int a = 10;
*
* Scala
* --变量
* var 变量名:数据类型 = 值
* var a:Int = 10
* --常量
* val 变量名:数据类型 = 值
* val a:Int = 10
*/
object Scala02_var {
/* (0)声明一个整数类型的变量a,并给其赋值
var a: Int = 10
println(a)
*/
/* (1)声明变量时,类型可以省略,编译器自动推导,即类型推导
var a = 10 等同于 var a: Int = 10
println(a)
*/
/* (2)类型确定后,就不能修改,说明Scala是强数据类型语言。
var a = 10
a = "123" ×
*/
/* (3)变量声明时,必须要有初始值。不同于Java,Scala在声明同时必须赋值
var a:Int ×
println(a)
*/
/* (4)在声明/定义一个变量时,可以使用var或者val来修饰,var修饰的变量可改变
var a = 10
val b = 20
a = 15
b = 25 Reassignment to val
*/
/* (5)var修饰的对象引用可以改变,val修饰的对象则不可改变,但对象的状态(值)却是可以改变的。(比如:自定义对象、数组、集合等等)
var std1 = new Student()
std1 = new Student
val std2 = new Student()
std2.name = "lisi"
std2 = new Student
*/
/* (6)在实际开发过程中,var和val优先选哪个
val
*/
}
class Student{
var name:String = "zhangsan"
}
2、标识符的命名规范
Scala对各种变量、方法、函数等命名时使用的字符序列称为标识符。即:凡是自己可以起名字的地方都叫标识符。
1)命名规则
Scala中的标识符声明,基本和Java是一致的,但是细节上会有所变化,有以下四种规则:
(1)以字母或者下划线开头,后接字母、数字、下划线
(2)以操作符开头,且只包含操作符(+ - * / # !等)
(3)用反引号`....`包括的任意字符串,即使是Scala关键字(39个)也可以
- package, import, class, object, trait, extends, with, type, for
- private, protected, abstract, sealed, final, implicit, lazy, override
- try, catch, finally, throw
- if, else, match, case, do, while, for, return, yield
- def, val, var
- this, super
- new
- true, false, null
object TestName {
def main(args: Array[String]): Unit = {
// (1)以字母或者下划线开头,后接字母、数字、下划线
var hello: String = "" // ok
var Hello12: String = "" // ok
var 1hello: String = "" // error 数字不能开头
var h-b: String = "" // error 不能用-
var x h: String = "" // error 不能有空格
var h_4: String = "" // ok
var _ab: String = "" // ok
var Int: String = "" // ok 因为在Scala中Int是预定义的字符,不是关键字,但不推荐
var _: String = "hello" // ok 单独一个下划线不可以作为标识符,因为_被认为是一个方法
println(_)
//(2)以操作符开头,且只包含操作符(+ - * / # !等)
var +*-/#! : String = "" // ok
var +*-/#!1 : String = "" // error 以操作符开头,必须都是操作符
//(3)用反引号`....`包括的任意字符串,即使是Scala关键字(39个)也可以
var if : String = "" // error 不能用关键字
var `if` : String = "" // ok 用反引号`....`包括的任意字符串,包括关键字
}
}
3、字符串输出
package com.scala.chapter02
/**
* 字符串输出
*/
object Scala03_TestString {
def main(args: Array[String]): Unit = {
//(1)字符串,通过+号连接
var name: String = "xiaoming"
var age: Int = 12
// println(age + "岁的" + name + "在学习")
//(2)printf用法:字符串,通过%传值。
printf("%d岁的%s在学习", age, name)
printf(s"${age}岁的${name}在学习", age, name)
//(3)字符串模板(插值字符串):通过$获取变量值
//多行字符串,在Scala中,利用三个双引号包围多行字符串就可以实现。
//输入的内容,带有空格、\t之类,导致每一行的开始位置不能整洁对齐。
//应用scala的stripMargin方法,在scala中stripMargin默认是“|”作为连接符,
//在多行换行的行头前面加一个“|”符号即可。
var sql: String =
s"""
select
*
from
student
where
name = ${name}
and
age = ${age}
""".stripMargin
println(sql)
}
}
4、键盘输入
在编程中,需要接收用户输入的数据,就可以使用键盘输入语句来获取。
1)基本语法
StdIn.readLine()、StdIn.readShort()、StdIn.readDouble()
package com.scala.chapter02
import scala.io.StdIn
/**
* 获取用户键盘输入
*/
object Scala04_TestStdIn {
def main(args: Array[String]): Unit = {
println("请输入用户名")
val name = StdIn.readLine()
println("请输入年龄")
val age = StdIn.readInt()
println(s"欢迎${age}岁的${name}加入")
}
}
5、数据类型
Java数据类型
Scala数据类型
6、 整数类型(Byte、Short、Int、Long)
Scala的整数类型就是用于存放整数值的,比如12,30,3456等等。
1)整型分类
数据类型 |
描述 |
Byte [1] |
8位有符号补码整数。数值区间为 -128 到 127 |
Short [2] |
16位有符号补码整数。数值区间为 -32768 到 32767 |
Int [4] |
32位有符号补码整数。数值区间为 -2147483648 到 2147483647 |
Long [8] |
64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807 = 2的(64-1)次方-1 |
2)案例实操
(1)Scala各整数类型有固定的表示范围和字段长度,不受具体操作的影响,以保证Scala程序的可移植性。
object TestDataType {
def main(args: Array[String]): Unit = {
// 正确
var n1:Byte = 127
var n2:Byte = -128
// 错误
// var n3:Byte = 128
// var n4:Byte = -129
}
}
(2)Scala的整型,默认为Int型,声明Long型,须后加‘l’或‘L’
object TestDataType {
def main(args: Array[String]): Unit = {
var n5 = 10
println(n5)
var n6 = 9223372036854775807L
println(n6)
}
}
(3)Scala程序中变量常声明为Int型,除非不足以表示大数,才使用Long
7、浮点类型(Float、Double)
Scala的浮点类型可以表示一个小数,比如123.4f,7.8,0.12等等。
1)浮点型分类
数据类型 |
描述 |
Float [4] |
32 位, IEEE 754标准的单精度浮点数 |
Double [8] |
|
2)案例实操
Scala的浮点型常量默认为Double型,声明Float型常量,须后加‘f’或‘F’。
object TestDataType {
def main(args: Array[String]): Unit = {
// 建议,在开发中需要高精度小数时,请选择Double
var n7 = 2.2345678912f
var n8 = 2.2345678912
println("n7=" + n7)
println("n8=" + n8)
}
}
//运行的结果
n7=2.2345679
n8=2.2345678912
8、字符类型(Char)
1)基本说明
字符类型可以表示单个字符,字符类型是Char。
2)案例实操
(1)字符常量是用单引号 ' ' 括起来的单个字符。
(2)\t :一个制表位,实现对齐的功能
(3)\n :换行符
(4)\\ :表示\
(5)\" :表示"
package com.scala.chapter02
/**
* char字符类型
*/
object Scala07_CharType {
def main(args: Array[String]): Unit = {
//(1)字符常量是用单引号 ' ' 括起来的单个字符。
var c1: Char = 'a'
println("c1=" + c1)
//注意:这里涉及自动类型提升,其实编译器可以自定判断是否超出范围,
//不过idea提示报错
var c2: Char = 'a' + 1
println(c2)
//(2)\t :一个制表位,实现对齐的功能
println("姓名\t年龄")
//(3)\n :换行符
println("张三\n李四")
//(4)\\ :表示\
println("d:\\学习资料\\avi")
//(5)\" :表示"
println("张三:\"hello\"")
}
}
9、布尔类型:Boolean
1)基本说明
(1)布尔类型也叫Boolean类型,Booolean类型数据只允许取值true和false
(2)boolean类型占1个字节。
2)案例实操
object TestBooleanType {
def main(args: Array[String]): Unit = {
var isResult : Boolean = false
var isResult2 : Boolean = true
}
}
10、Unit类型、Null类型和Nothing类型
1)基本说明
数据类型 |
描述 |
Unit |
表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。 |
Null |
null , Null 类型只有一个实例值null |
Nothing |
Nothing类型在Scala的类层级最低端;它是任何其他类型的子类型。 当一个函数,我们确定没有正常的返回值,可以用Nothing来指定返回类型,这样有一个好处,就是我们可以把返回的值(异常)赋给其它的函数或者变量(兼容性) |
2)案例实操
(1)Unit类型用来标识过程,也就是没有明确返回值的函数。
由此可见,Unit类似于Java里的void。Unit只有一个实例——( ),这个实例也没有实质意义
def main(args: Array[String]): Unit = {
def sayOk : Unit = {// unit表示没有返回值,即void
}
println(sayOk)
}
}
(2)Null类只有一个实例对象,Null类似于Java中的null引用。Null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)
object TestDataType {
def main(args: Array[String]): Unit = {
//null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)
var cat = new Cat();
cat = null // 正确
var n1: Int = null // 错误
println("n1:" + n1)
}
}
class Cat {
}
(3)Nothing,可以作为没有正常返回值的方法的返回类型,非常直观的告诉你这个方法不会正常返回,而且由于Nothing是其他任意类型的子类,他还能跟要求返回值的方法兼容。
object TestSpecialType {
def main(args: Array[String]): Unit = {
def test() : Nothing={
throw new Exception()
}
test
}
}
11、类型转换
1.Java中的隐式类型转换
package com.scala.chapter01;
public class Test {
public static void main(String[] args) {
byte b = 10;
test(b); //默认调用同类型方法,无同类型寻找接近的类型,不会使用char
}
private static void test(byte b) {
System.out.println("byte");
}
private static void test(short b) {
System.out.println("short");
}
private static void test(char b) {
System.out.println("char");
}
private static void test(int b) {
System.out.println("int");
}
}
2.当Scala程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数值类型,这个就是自动类型转换(隐式转换)。数据类型按精度(容量)大小排序为:
1)基本说明
(1)自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数据类型,然后再进行计算。
(2)把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。
(3)(byte,short)和char之间不会相互自动转换。
(4)byte,short,char他们三者可以计算,在计算时首先转换为int类型。
package com.scala.chapter02
/**
* 类型转换
* 自动类型转换
* 强转
*/
object Scala08_DataType {
def main(args: Array[String]): Unit = {
/*(1)自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数据类型,然后再进行计算。
var b1:Byte = 10
var n:Long = 20L
var res = n + b1
*/
/*(2)把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。
var b:Byte = 10
var n:Int = b //将精度小的数据赋值给精度大的类型,会自动进行转换(隐式转换)
var b2:Byte = n //精度大的数值类型赋值给精度小的数值类型时,就会报错
*/
/*(3)(byte,short)和char之间不会相互自动转换。
var b:Byte = 10
var c:Char = b
var c1:Char = 96
var n:Int = c1
*/
//(4)byte,short,char他们三者可以计算,在计算时首先转换为int类型。
var b: Byte = 10
var s: Short = 20
var c: Char = 30
val res: Int = b + s + c
}
}
3.强制类型转换
1)基本说明
自动类型转换的逆过程,将精度大的数值类型转换为精度小的数值类型。使用时要加上强制转函数,但可能造成精度降低或溢出,格外要注意。
Java :
int num = (int)2.5
Scala :
var n: Int = 2.5.toInt
2)案例实操
(1)将数据由高精度转换为低精度,就需要使用到强制转换
(2)强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
//(1)将数据由高精度转换为低精度,就需要使用到强制转换
var n1: Int = 2.5.toInt // 这个存在精度损失
//(2)强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
var r1: Int = 10 * 3.5.toInt + 6 * 1.5.toInt // 10 *3 + 6*1 = 36
var r2: Int = (10 * 3.5 + 6 * 1.5).toInt // 44.0.toInt = 44
println("r1=" + r1 + " r2=" + r2)
3.数值类型和String类型间转换
1)基本说明
在程序开发中,我们经常需要将基本数值类型转成String类型。或者将String类型转成基本数值类型。
2)案例实操
(1)基本类型转String类型(语法:将基本类型的值+"" 即可)
(2)String类型转基本数值类型(语法:s1.toInt、s1.toFloat、s1.toDouble、s1.toByte、s1.toLong、s1.toShort)
//(1)基本类型转String类型(语法:将基本类型的值+"" 空串即可)
var str1 : String = true + ""
var str2 : String = 4.5 + ""
var str3 : String = 100 + ""
//(2)String类型转基本数值类型(语法:调用相关API)
var s1 : String = "12"
var n1 : Byte = s1.toByte
var n2 : Short = s1.toShort
var n3 : Int = s1.toInt
var n4 : Long = s1.toLong
(3)注意事项
在将String类型转成基本数值类型时,要确保String类型能够转成有效的数据,比如我们可以把"123",转成一个整数,但是不能把"hello"转成一个整数。
var n5:Int = "12.6".toInt会出现NumberFormatException异常。
/**
* var b:Byte = 128.toByte
* 128在scala中默认是Int类型,应该是32位
* 源码 00000000 00000000 00000000 10000000
* 补码 00000000 00000000 00000000 10000000
* 对Int数据进行截取,截取为Byte,剩下8位 ==》10000000 约定当前值为范围最小值-128
*
* var b:Byte = 130.toByte
* 130在scala中默认是Int类型,应该是32位
* 源码 00000000 00000000 00000000 10000010
* 补码 00000000 00000000 00000000 10000010
* Int数据进行截取,截取为Byte,剩下8位 负数补码10000010==》反码:11111101--》源码11111110
*
* var b:Byte = -130.toByte
* 源码 10000000 00000000 00000000 10000010
* 反码 11111111 11111111 11111111 01111101
* 补码 11111111 11111111 11111111 01111110
* Int数据进行截取,截取为Byte,剩下8位 补码01111110==》反码:01111110--》源码01111110
*
*/
object Scala_DataType {
def main(args: Array[String]): Unit = {
var b:Byte = 128.toByte
println(b) //-128
}
}
数据类型小结
-Any
*AnyVal(值类型)
>Byte,Short,Int,Long,Float,Double,Boolean,Char
>Unit
表示返回值类型为空,相当于Java中的void关键字
>StringOps
对字符串功能的增强
*AnyRef(引用类型)
>所有Java语言中的类型
>Scala语言中的类
>集合
>Null
表示变量声明后,没有指向任何对象,相当于Java中null关键字
是所有AnyRef的子类,所以不能将null赋值给AnyValue
*Nothing
是所有类的子类,一般用于方法的返回值,表示当前方法没有正常返回的情况
第3章 运算符
Scala运算符的使用和Java运算符的使用基本相同,只有个别细节上不同。
1、算术运算符
1)基本语法
运算符 |
运算 |
范例 |
结果 |
+ |
正号 |
+3 |
3 |
- |
负号 |
b=4; -b |
-4 |
+ |
加 |
5+5 |
10 |
- |
减 |
6-4 |
2 |
* |
乘 |
3*4 |
12 |
/ |
除 |
5/5 |
1 |
% |
取模(取余) |
7%5 |
2 |
+ |
字符串相加 |
“He”+”llo” |
“Hello” |
(1)对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。
(2)对一个数取模a%b,和Java的取模规则一样。
//-------------------------------算术运算符--------------------------------------
//(1)对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。
var r1: Int = 10 / 3 // 3
println("r1=" + r1)
var r2: Double = 10 / 3 // 3.0
println("r2=" + r2)
var r3: Double = 10.0 / 3 // 3.3333
println("r3=" + r3)
println("r3=" + r3.formatted("%.2f")) // 含义:保留小数点2位,使用四舍五入
//(2)对一个数取模a%b,和Java的取模规则一样。
var r4 = 10 % 3 // 1
println("r4=" + r4)
2、关系运算符(比较运算符)
1)基本语法
运算符 |
运算 |
范例 |
结果 |
== |
相等于 |
4==3 |
false |
!= |
不等于 |
4!=3 |
true |
< |
小于 |
4<3 |
false |
> |
大于 |
4>3 |
true |
<= |
小于等于 |
4<=3 |
false |
>= |
大于等于 |
4>=3 |
true |
2)案例实操
(1)需求1:
// 测试:>、>=、<=、<、==、!=
var a: Int = 2
var b: Int = 1
println(a > b) // true
println(a >= b) // true
println(a <= b) // false
println(a < b) // false
println("a==b" + (a == b)) // false
println(a != b) // true
(2)需求2:Java和Scala中关于==的区别
/**
* Java
* ==比较的是对象的内存地址
* equals 默认是和 "==" 一样 , 也是比较的地址,String对quals方法进行了重写,字符串的equals比较的是内容
*
* Scala
* ==和equals和功能一样,比较的是内容是否相同
* 反编译
* String s1 = new String("abc");
* String s2 = "abc";
* String str1 = s2;
* String tmp163_157 = s1; tmp163_157; if (str1 != null) { if (!Predef..MODULE$.equals(str1)); } else { tmpTernaryOp = (tmp163_157 == null ? tmp163_157 : 1); break label189; }
* }
* eq 等同于Java中的equals,比较对象的内存地址
*
*/
var s1: String = new String("abc")
var s2: String = "abc"
println(s1 == s2) //true
println(s1.equals(s2)) //true
println(s1.eq(s2)) //false
3、逻辑运算符
1)基本语法
用于连接多个条件(一般来讲就是关系表达式),最终的结果也是一个Boolean值。
假定:变量A为true,B为false
运算符 |
描述 |
实例 |
&& |
逻辑与 |
(A && B) 运算结果为 false |
|| |
逻辑或 |
(A || B) 运算结果为 true |
! |
逻辑非 |
!(A && B) 运算结果为 true |
2)案例实操
// 测试:&&、||、!
var a = true
var b = false
println("a&&b=" + (a && b)) // a&&b=false
println("a||b=" + (a || b)) // a||b=true
println("!(a&&b)=" + (!(a && b))) // !(a&&b)=true
}
}
//扩展避免逻辑与空指针异常
isNotEmpty(String s){
//如果逻辑与,s为空,会发生空指针
return s!=null && !"".equals(s.trim());
}
4、赋值运算符
1)基本语法
赋值运算符就是将某个运算后的值,赋给指定的变量。
运算符 |
描述 |
实例 |
= |
简单的赋值运算符,将一个表达式的值赋给一个左值 |
C = A + B 将 A + B 表达式结果赋值给 C |
+= |
相加后再赋值 |
C += A 等于 C = C + A |
-= |
相减后再赋值 |
C -= A 等于 C = C - A |
*= |
相乘后再赋值 |
C *= A 等于 C = C * A |
/= |
相除后再赋值 |
C /= A 等于 C = C / A |
%= |
求余后再赋值 |
C %= A 等于 C = C % A |
<<= |
左移后赋值 |
C <<= 2等于 C = C << 2 |
>>= |
右移后赋值 |
C >>= 2 等于 C = C >> 2 |
&= |
按位与后赋值 |
C &= 2 等于 C = C & 2 |
^= |
按位异或后赋值 |
C ^= 2 等于 C = C ^ 2 |
|= |
按位或后赋值 |
C |= 2 等于 C = C | 2 |
注意:Scala中没有++、--操作符,可以通过+=、-=来实现同样的效果;
//在java语言中,+=运算符可以自动进行强转,但是在scala语言中,+=底层不会自动进行强转
// var b:Byte =10
var b:Int =10
b +=1
println(b)
def main(args: Array[String]): Unit = {
var r1 = 10
r1 += 1 // 没有++
r1 -= 2 // 没有--
}
5.位运算符
1)基本语法
变量 a = 60,b = 13。
运算符 |
描述 |
实例 |
& |
按位与运算符 |
(a & b) 输出结果 12 ,二进制解释: 0000 1100 |
| |
按位或运算符 |
(a | b) 输出结果 61 ,二进制解释: 0011 1101 |
^ |
按位异或运算符 |
(a ^ b) 输出结果 49 ,二进制解释: 0011 0001 |
tan丶90: 请问在哪里解决
竹霖聴雨: 博主好,假设(可能不恰当)要计算每近1、7、30天的uv_count除以avg_duration_sec的值,应该如何操作呀提前感谢博主~
同花讲古同鱼冲凉: 硅谷大神