Scala的变量
声明变量
var i:Int=0
var score:Double=1.1
注意事项:
1、声明变量的时候类型可以省略,叫做类型推断
2、类型一旦确定就不能修改说明scala是强类型语言
3、var声明的表示为可变变量,val声明的为不可变变量
4、变量声明的时候必须有初始值
Scala的类型介绍:
1、Scala是完全面向对象的,所以没有原生类型:比如int,double等
2、Scala的数据类型分为两大类:AnyVal(值类型)、AnyRef(引用类型),但他们都是对象
数据类型 | 描述 |
---|---|
Byte | 8位有符号补码整形,数值范围:-128–127 |
Char | 16位有符号补码整形 |
Short | 16位补码整形 |
Int | 32位 |
Float | 32位 |
Long | 64位 |
Double | 64位 |
String | 字符序列 |
Boolean | false或true |
Unit | 就是void |
Null | null |
Nothing | 他是所有Scala类层的最低层,是任何其他类型的子类型 |
Any | 是所有其他类型的超类 |
AnyRef | 是Scala所有引用类型的基类 |
Null可以使AnyRef的赋值但是不可以赋值给AnyVal
Unit就相当于void
Nothing,可以作为没有正常返回值的方法的返回类型,直观的告诉你这个方法不会正常返回
自动类型转换(隐式转换)
1、当有多重类型进行计算的时候,会首先将所有类型都转换成精度大的类型进行计算
2、当我们把精度大的类型赋值给精度小的类型时候会报错,反之会进行自动类型转换
3、(Byte和short)不会和char之间自动转换(图中也可以看出)
4、byte、short、char之间可以进行计算但是首先他们要转换成Int
5、表达式的结果类型就是操作数中最大的类型
值的类型强制转换
就是大精度变小精度:
举例:
var num:Int=3.5.toInt
Byte和Short当做Int处理
算数运算符
基本运算同java,但是注意Scala没有++, - -的操作,只能用+=,-=
流程控制
if同java。
我们介绍一下在Scala中没有switc取而代之的是模式匹配:
for语句:
1、范围数据循环方式:
for(i <- 1 to 3)
{
print(i+" ")
}
to包含前后即输出为1、2、3
2、方式2:
for(i <- 1 until 3)
这个是前闭后开的即1、2
循环守卫:
for(i <- 1 to 3 if i !=2)
{
print(i+" ")
}
循环守卫判断为false的时候就相当于continue。
引入变量:
for(i <- 1 to 3 ; j=i-4)
{
print(j+" ")
}
因为中间没有关键字所以用;隔开,其实这个表达式就类似于将j=i-4放入循环体中一样
嵌套
for(i <- 1 to 3 ;j<- 1 until 4)
{
print(i*j)
}
其实就等同于:
for(i <- 1 to 3)
{
for(j<- 1 until 4)
{
print(i*j)
}
}
for的步长控制:
for(i <- Range(1,3,2))
Range第一个参数为头,第二个为尾第三个为步长
循环的返回值
var res=for(i <- 1 to 5)
{
yield i*2
}
print(res)
循环的中断
Scala中去掉了break和continue关键字取而代之的是:
breakable{
for(i <- 1 to 20){
if (i ==18)
{
break();
}
}
}
continue的替代方式为循环守卫上面介绍了
函数式编程
- 函数的定义
def 函数名 (参数列表)【:返回值类型=】{
语句
return 返回值 如果没有return则默认为最后一行计算结果
}
比如:
def sum(a:Int,b:Int):Int={
return a+b
}
def sum2(a:Int,b:Int)={
a+b //因为返回值没写所以自动推断
}
def myprint(a:String):Unit={
print(a)
}
参数默认初始化:
def myprint(url:String="doudou"){
print(url)
}
如果调用上面函数没有传入url则默认值。
可变参数:
def myprint(a:String*):Unit={
}
java为…而我们的Scala则用*号
方法和函数
例如:
def f1():Int={100}
var f2=f1 //错误的
var f3=f1_
要想把方法变成函数就在方法的名称后加_
匿名函数
jvaa中的匿名函数:(lamda表达式):
(参数列表)-> {方法体}
Scala中的匿名函数:
(参数列表)=> {方法体}
高阶函数
将其他函数作为参数或者返回值的函数:
def apple(f:(a:String)=>Unit,c:String){
f(c)
}
def f(a:String):Unit={
print(a)
}
def main(args:Array[String]):Unit{
apple(f,"cd")
}
函数的返回值是一个函数:
def()={
(d:Double)=>{print(d+" ")}
}
函数的柯里化:
柯里化就是将函数的多个参数变成一个参数:例如:
//原来的函数
def addMulti(a:Int,b:Int)={a*b}
//柯里化:
def addMultiK(a:Int)(b:Int)={a*b}
参数推断:
简化流程:
1、list中都为Int所以可以不给x显示为Int
2、因为x在右边只出现一次所以可以直接省略成_变成_+1
惰性函数
当函数返回值被声明为lazy,函数的执行将被延迟,直到首次取值:
def sum(a:Int,b:Int)={a+b}
def fun()={
lazy val res=sum(1,2);
}
lazy不只是可以修饰函数而其还可以修饰变量,变量的分配就会推迟,但是lazy只能修饰val的变量
面向对象
注意:
- Scala中的类默认就是共有可见的。
- 一个Scala源文件可以有多个类
- 类的属性必须赋初值如果不想赋值那么也要用_来让系统默认赋值
- Scala类的构造器:包括主构造器和辅助构造器:语法:
class demo(构造器参数){
def this(参数列表){
//辅助构造器
}
}
辅助构造器的名称为this,可以有多个,编译器通过不同的参数来区分辅助构造器。
构造器没有返回值,柱构造器也是一个方法他会执行里面的所有函数,如果柱构造器的参数为空可以省略(),我们在new的时候也可以省略()。
class demo(){
var name:String=_
def this(name:String){
this();//辅助构造器无论直接或间接都要调用柱构造器,而且放在辅助构造器的第一行
this.name=name
}
}
如果不想让用户new我们的对象我们可以在柱构造器的参数列表的()前+private:
class demo private(){
var name:String=_
def this(name:String){
this();//辅助构造器无论直接或间接都要调用柱构造器,而且放在辅助构造器的第一行
this.name=name
}
}
- 构造器的参数:
当我们的参数像上面一样没有任何修饰的时候那么他其实就是一个局部变量,当我们加上val的时候他就变成了只读的私有的成员变量,如果我们加上var那么他就是成员属性并且是私有的但是提供了类似于get和set的方法。
class demo(var name:String){
}
class demo1(val name:String){
}
成员属性的get和set方法,因为我们在用java的时候很多框架或者工具都依赖属性的get和set方法那么我们怎么在Scala中给属性加上get和set方法呢,这里引入了@BeanPropetry注解:
class demo(){
@BeanPropetry
var name:String=_;
}
面向对象的三大特点:
继承、封装、多态:
继承:只有柱构造器才能调用父类的构造器:
class Persionn{
}
class Man extends Persion{
super;
def this(){
~~super~~ //不可以在这调用
}
}
在Scala中属性也是能不复写的只需要加上override:
class A{
val name:String=_
}
class B extends A{
override val name:String="doubi";
}
我们可以在这回忆一下java的动态绑定:看看下面代码输出结果
class A {
public int i = 10;
public int sum() {
return i + 20;
}
public int sum1() {
return getI() + 10;
}
public int getI() {
return i;
}
}
class B extends A {
public int i = 20;
public int getI() {
return i;
}
// public int sum() {
// return i + 20;
// }
// public int sum1() {
// return getI() + 10;
// }
我们在主函数调用如下:
public static void main(String[] args) throws IOException {
B b=new B();
b.sum;//此时肯定为40继承
//todo 而当我们注释掉B的sum方式后:
b.sum;//此时可以看到结果为30,因为子类继承了父类的方法,就会调用父类的sum函数但是此时的i变量只能为父类的i即为20
// todo 我们在看如下代码,并注释掉B的sum1
A a=new B();
a.sum1();//返回值为30,过程为:这就是方法的动态绑定而属性没有:调用a.sum1的时候首先会先去分配内存的对象实例中去加载方法(即方法的动态绑定)这时实际分配的对象实例为B因为new的B,所以就先去b中找有么已有sum1?一看有一个只是是从父类中继承过来的,所以总到了父类的sum1中此时,发现父类中的sum1中又调用了getI,注意 这是个方法要去内存绑定的类中找所以找到了B中的getI,而属性此时没有动态绑定,在B中国的getI方法调用的是this.i所以返回的是B的20,在+A中的sum1中的10就是30了
}
上面的过程简单的记为:方法看分配内存的对像的方法,而属性是就近原则,在父类中就用父类的在子类中就用子类的。
伴生对象:
因为Scala是完全面向对象的所以没有静态的static关键字,因为有这个关键字的时候我们调用方法并不是通过new对象来创建的所以和,而Scala是完全面向对象的所以没有这个关键字。
class demo{
var name:String=_;
}
object demo{
var sex:Boolean=true;
}
上面的class对象就是半生类,而object就是伴生对象
1、Scala通过object关键字来声明伴生对象,伴生对象中声明的全是静态内容
2、伴生对象的属性和方法都可以通过伴生对象名直接调用
接口:
Scala采用了trait关键字来替代接口:
trait Demo{
}
trait Demo2{}
class demo1 extends Demo with Demo2{
}
trait的trait体中可以有非抽象方法,当然也可以有抽象的方法
.动态混入
可以在构建对象的时候将特征混入比如:
trait a {
def mp():Unit={
print("is run")
}
class option1{
}
def main(args:String[])
{
option1 o=new option1() whith a;
o.mp();
}
}
内部类:
java的内部类:
class out{
class in{
}
}
public static void mian(String args[]){
out o=new out();
in i=o.new in()
}
scala的内部类:
class out{
class in{
}
}
def main(args:String[]){
var o:out=new out();
var i:in=new o.in();
}
内部类要想访问外部类的属性可以通过:外部类名称.this.属性名,也可以通过给外部类起别名例如:
class demo{
outclass=>
class in{
print(outclass.name)
}
private name:String=_//当其别名的时候属性放到后边
}
隐式转换:
隐式转换是使用implicit关键字来声明带有单个参数的函数。这种函数会自动应用,将值从一个类型转换成另一个类型。举例:
implicit def f1(d:Double){
d.toInt
}
1、隐式转换只与函数的签名(参数和返回值)有关和函数名称无关
2、可以有多个但是必须保证能在当前环境中唯一识别
什么时候进行隐式转换:
1、当目标类型和输出类型不一致的时候
2、当对象调用的类在本类中不存在
Scala集合:
Scala的集合分为可变集合和不可变集合,其主要分为三大类:Seq、set、map,其中可变集合的意思是其长度可以改变的集合类似于java里面的arrayList,而不可变集合类似于数组。
- 元组:tuple:元组就是可以将各种类型的数据进行组合的一种容器,元组最大只能有22个元素:
元组的创建:
val tuple1=(1,"doudou",1.2)
//或者:
val tuple=2=>"doubi"//类似于key,Val的方式
元组的访问:
object TupleDemo
{
def main(args:Array[String]):Unit={
val tuple1=(1,"doudou",1.2)
//1、顺序访问:
print(tuple1_1)//输出1
print(tuple1_2)//输出doudou
//第二种角标访问:
print(tuple1.productElement(0))//从0开始
}
}
元组是一个整体当我们要对其进行遍历的时候需要用他的迭代器:
object demo{
def main(args:Array[String]):Unit={
val tuple1=(1,"doudou",1.2)
for(item <- tuple1.productIterator)
{
//逻辑
}
}
}
- 定长数组:
object demo{
def main(args:Array[String]):Unit={
//1、第一种
val arr=new Array[Int](10);
arr(7)=0;
//2、
val arr2=Array(1,2,3)
for(item<-arr2)
{
printf(item)
}
}
}
- 可变数组:
object demo{
def main(args:Array[String]):Unit={
val arrbuf=new ArrayBuffer[Int]();
arrbuf.append(1)
arrbuf(0)=7
}
}
可变数组和不可变数组之间可以互相转换:不可变变成可变:arr.toBuffer变成;可变变成不可变arrbuf.toArray
- List,Scala的list不同与java的list他不是接口可以直接存放数据,他隶属于Seq:
object demo{
def main(args:Array[String]):Unit={
val list=List(1,2,5)
创建的时候直接分配元素
val list2=Nil//空集合
list1(0)//取出的是1
}
list的追加数据同java不太一样:
a. 向list中尾部添加数据
object demo{
def main(args:Array[String]):Unit={
val list=List(1,2,5)
var list2=list:+4
}
b、向list前面添加数据:
object demo{
def main(args:Array[String]):Unit={
val list=List(1,2,5)
var list2=4+:list
}
c、添加:
```scala
object demo{
def main(args:Array[String]):Unit={
val list=4::5::6::Nil//从右向左看,一开始是创建了一个空的集合,然后往里面加了个6,之后加了个5依次
val list2=8::7::list::Nil//最后list2为【8,7,【4,5,6】】放进去的是集合
val list3=9::10::list:::Nil//注意此时结果是【9,10,4,5,6】
}
当添加的元素不是集合的时候用::或者+:当是要求将集合中的数存入新集合用:::
5、可变的list-》ListBuffer
object demo{
def main(args:Array[String]):Unit={
val listbuf=ListBuffer[Int](1,2,3)
val listbuf2=new ListBuffer[Int]
//1、添加元素
listbuf+=21
listbuf2.append(1)
listbuf2.append(2)
listbuf2:+4//尾部添加同理
//2、删除元素
listbuf -=1//删除1从集合里面
listbuf.remove(1)//删除角标为1的元素
listbuf2--=Seq(1,2)
//3、拼接两个list
val list=listbuf++listbuf2//或者:::
}
}
6、队列:Queue
object demo{
def main(args:Array[String]):Unit={
val q=new mutable.Queue[Int]
//向queue中添加数据:
q+=1;
val list=List(1,2,3)
q++=list//添加集合
//队列的删除
q.dequeue()
//给队里添加数据:
q.enqueue(1,8,9)
//返回队列头
q.head
//返回队列尾
q.last
//返回除第一个以外的数据
q.tail
//还可以级联
q.tail.tail
}
}
7、map:
object demo{
def main(args:Array[String]):Unit={
val map=Map(1->"maga",2->"doudou")
val map2=new Map[Int,String]
val map3=Map((1,"doubi"),(2,"gg"))
//取值:
map(1)
map.get(x)//get返回的是option要么是None要么是Some,因为我们map中没有键x所以返回为None
map.get(1).get//为什么有两个get呢?第一个取到的为some第二个取到的为some里面的值
map.getOrElse(1,“没有”)第一个参数为取的key第二个是如果没有则返回的默认值
//如果我们要快速找到值就用()的方式
//如果我们要判断key是不是存在就用contains
//如果单纯的就是要取出来用getOrElse
修改和添加:
map(10)="dedee"//如果含有这个key就修改没有就添加这个key和v
添加:
map+=(10->“ceshi”)//添加一个
map+=(11->“dd”,12->"ff")
删除:
map-=(11,1,12)//括号内是要删除的key
//遍历:除了这个还有很多种
for((k,v)<-map)
{
//逻辑
}
}
}
8、set
object demo{
def main(args:Array[String]):Unit={
//创建:
val set=Set(1,2,3)
val set2=new Set[Int]
//添加:
set.add(4)
set+=5//因为是set所以如果添加的是已经含有的则不会添加
//删除
set-=1
set.remove(2)
//遍历
for(tep<-set)
{
tep
}
}
}
应用操作结合java8的stream回顾:
Scala中的:
函数名称 | 参数解析 | 举例 |
---|---|---|
map | 集合元素映射,参数为一个函数f,就是取出每个元素然后进行f(元素)操作 | map例子 |
flatmap | 将集合中的每个元素进行处理变成集合返回 | flatmap |
filter | 传入一个返回值为boolean的函数,将符合条件的返回不符合过滤掉 | filter |
reduce | 化简或者规约,就是从元素的第一个开始取一个同下一个进行f(a,b)操作 | reduce |
fold | 折叠,这个实际上十分想上面的reduce只不过他的第一个待计算的参数自己指定 | fold |
zip | 开发中我们需要将两个集合元素进行对偶可以使用 | zip |
iterator | 迭代器 | iterator |
1、map:
val list1 = List(3, 5, 7)
def f1(n1: Int): Int = {
2 * n1
}
val list2 = list1.map(f1)
println(list2)//返回的任然是个list里面的值为原来的值*2
2、flatmap:
object Demo {
def main(args: Array[String]): Unit = {
val names = List("Al-ice", "Bo-b", "Ni-c-k")
println(names.flatMap((x) => x.split("-")))
}
}
//输出结果:
List(Al, ice, Bo, b, Ni, c, k)
3、filter
object Demo {
def main(args: Array[String]): Unit = {
val names = List(1,2,3,4,5,6,7,8,9,10)
println(names.filter(_ % 2 == 0))
}
}
//返回结果
List(2, 4, 6, 8, 10)
4、reduce
object Demo {
def main(args: Array[String]): Unit = {
val names = List(1,2,3,4,5,6,7,8,9,10)
println(names.reduce(_ + _))
}
}
//返回值为55
5、fold
object Demo {
def main(args: Array[String]): Unit = {
val names = List(1,2,3,4,5,6,7,8,9,10)
println(names.foldLeft(0)(_+_))
}
}
//结果55
他还可以简写成foldLeft等价于/:
foldRight等价于:
使用:
val list4 = List(1, 9, 2, 8)
def minus(num1: Int, num2: Int): Int = {
num1 - num2
}
var i6 = (1 /: list4) (minus)
println(i6)
i6 = (100 /: list4) (minus)
println(i6)
i6 = (list4 :\ 10) (minus)
println(i6)
6、zip
object Demo {
def main(args: Array[String]): Unit = {
val names = List(1,2,3,4,5)
val name2=List(6,7,8,9,10)
println(names.zip(name2))
}
}
//返回结果:List((1,6), (2,7), (3,8), (4,9), (5,10))
注意如果两个集合的数据量不对等那么就会造成数据丢失
7、iterator
val iterator1 = List(1, 2, 3, 4, 5).iterator // 得到迭代器
println("--------遍历方式1 -----------------")
while (iterator1.hasNext) {
println(iterator1.next())
}
println("--------遍历方式2 for -----------------")
val iterator2 = List(11, 22, 33, 44, 55).iterator // 得到迭代器
for(enum <- iterator2) {
println(enum) //
}
java中的Stream:
有了stream我们就可以将计算过程抽象为如下:
±-------------------+ ±-----+ ±-----+ ±–+ ±------+
| stream of elements ±----> |filter±> |sorted±> |map±> |collect|
±-------------------+ ±-----+ ±-----+ ±–+ ±------+
其java实现的代码:
List<Integer> transactionsIds =
widgets.stream()
.filter(b -> b.getColor() == RED)
.sorted((x,y) -> x.getWeight() - y.getWeight())
.mapToInt(Widget::getWeight)
.sum();
java中如何获取stream流:
1、通过集合的stream()或者parallelStream()将集合转为stream
2、通过Stream的方法of将集合变成stream流:
Stream s=new Stream();
s.of(1,2,3)
或者
String str=new String[]{5,6,7};
s.of(str)
基本数据类型提供的stream
目前对于基本数据类型只有三个实现了stream:IntStream、LongStream、DoubleStream
数值流的构造
IntStream.range(1,10).forEach(System.out::println);//1到9
IntStream.of(1,2,5,8,10).forEach(System.out::println);
IntStream.rangeClosed(1,11).forEach(System.out::println);//1到11
stream常用操作:
函数名称 | 使用参数 | 举例 |
---|---|---|
map | 用法同Scala的map一样 | |
flatMap | 同Scala一样 | |
filter | 同Scala一样 | |
reduce | 类似于Scala的fold | reduce |
limit | 截取流 | limit |
skip | 就是跳过几个 | 举例 |
sorted | 对流进行排序,传一个函数用于排序 | sorted |
max/min/distinct | 看举例 | max、distinct |
match | stream有三种match:allmatch、nonematch、anyMatch | allmatch、nonematch、anyMatch |
无限流 | 自己产生流 | 无限流 |
1、limit
IntStream.rangeClosed(1,11).limit(5).forEach(System.out::println);
//结果:
1
2
3
4
5
2、sorted
List<Integer>list=new ArrayList<Integer>();
list.add(2);
list.add(1);
list.add(8);
list.add(5);
list.add(9);
list.add(7);
list.forEach(System.out::println);
list .stream().sorted().forEach(System.out::println);
//结果为:
2
1
8
5
9
7
--------------------------
1
2
5
7
8
9
List<Integer>list=new ArrayList<Integer>();
list.add(2);
list.add(1);
list.add(8);
list.add(5);
list.add(9);
list.add(7);
list.forEach(System.out::println);
list .stream().sorted((a,b)->{return b.compareTo(a);}).forEach(System.out::println);
//输出结果为:
2
1
8
5
9
7
-----------
9
8
7
5
2
1
3、reduce:
Integer sum = integers.reduce(0, (a, b) -> a+b);
4、skip:
List<Integer>list=new ArrayList<Integer>();
list.add(2);
list.add(1);
list.add(8);
list.add(5);
list.add(9);
list.add(7);
// list.forEach(System.out::println);
list .stream().sorted((a,b)->{return b.compareTo(a);}).skip(2).forEach(System.out::println);
//结果为:
7
5
2
1
5、max
List<Integer>list=new ArrayList<Integer>();
list.add(2);
list.add(1);
list.add(8);
list.add(5);
list.add(9);
list.add(7);
System.out.println(list.stream().max((a, b) -> a.compareTo(b)).toString());
6、distinct
List<Integer>list=new ArrayList<Integer>();
list.add(2);
list.add(1);
list.add(8);
list.add(5);
list.add(9);
list.add(7);
list.add(7);
list.stream().distinct().forEach(System.out::println);
7、allmatch、nonematch、anyMatch
List<Integer>list=new ArrayList<Integer>();
list.add(2);
list.add(1);
list.add(8);
list.add(5);
list.add(9);
list.add(7);
list.add(7);
System.out.println(list.stream().allMatch(x -> x % 2 == 0));//所有都符合才是true
System.out.println(list.stream().noneMatch(x -> x % 2 == 0));//所有都不符合为true
System.out.println(list.stream().anyMatch(x -> x % 2 == 0));//有一个符合就位true
//结果为:
false
false
true
8、无限流:
Stream.iterate(new User("aa", 1, "1"), (u) -> {
u.setName(UUID.randomUUID().toString().substring(0,4));
Random random = new Random();
u.setOld(random.nextInt(100));
u.setId(UUID.randomUUID().toString().substring(5));
return u;
}).forEach(System.out::println);
Stream.generate(()->{
Random random = new Random();
return new User(UUID.randomUUID().toString().substring(0,4),random.nextInt(100),UUID.randomUUID().toString().substring(5));
}).forEach(System.out::println);
Collectors
java.util.stream.Collectors 类的主要作用就是辅助进行各类有用的 reduction 操作,例如转变输出为 Collection,把 Stream 元素进行归组。
主要就是讲产生的结果做进一步处理
函数 | 参数 | 举例 |
---|---|---|
groupingBy | 按照哪个字段分组 | groupingBy |
partitionBy | 按照给定的分组方式分组 | partitionBy |
结果转集合 | 结果转集合 | |
joining | 有三个参数第一个结果分隔符,第二个为首位置符号,第三个为尾位置符号 | joining |
统计结果 | 统计结果 |
1、groupingBy
List<Integer>list=new ArrayList<Integer>();
list.add(2);
list.add(1);
list.add(8);
list.add(5);
list.add(9);
list.add(7);
list.add(7);
System.out.println(list.stream().collect(Collectors.groupingBy(x -> x % 2 == 0)));
//结果:
{false=[1, 5, 9, 7, 7], true=[2, 8]}
2、partitionBy
System.out.println(list.stream().collect(Collectors.partitioningBy(x -> x % 2 == 0)));
返回值是一样的
3、结果转成集合
List<Integer>list=new ArrayList<Integer>();
list.add(2);
list.add(1);
list.add(8);
list.add(5);
list.add(9);
list.add(7);
list.add(7);
System.out.println(list.stream().collect(Collectors.toList()));
System.out.println(list.stream().collect(Collectors.toSet()));
4、joining
List<Integer>list=new ArrayList<Integer>();
list.add(2);
list.add(1);
list.add(8);
list.add(5);
list.add(9);
list.add(7);
list.add(7);
System.out.println(list.stream().map(x -> x.toString()).collect(Collectors.joining(",", "-", ")")));
/结果为:-2,1,8,5,9,7,7)
5、一些统计结果
统计总数量
List<Integer>list=new ArrayList<Integer>();
list.add(2);
list.add(1);
list.add(8);
list.add(5);
list.add(9);
list.add(7);
list.add(7);
Long i=list.stream().map(x -> x.toString()).collect(Collectors.counting());
System.out.println(i);
统计平均值:
User u1=new User("doudou",21,"1");
User u2=new User("jinmao",32,"2");
User u3=new User("hashiqi",42,"3");
User u4=new User("chiaquan",20,"4");
User u5=new User("xiangbin",52,"5");
List<User> users = new ArrayList<User>();
users.add(u1);
users.add(u2);
users.add(u3);
users.add(u4);
users.add(u5);
Integer collect = users.stream().collect(Collectors.summingInt(x -> x.getOld()));
System.out.println(collect);
//返回结果:
167
平均值同理:averagingDouble
还有一个可以返回上面所有的统计结果:
DoubleSummaryStatistics statistics = list.stream().collect(Collectors.summarizingDouble(Student::getAge));
System.out.println("count:" + statistics.getCount() + ",max:" + statistics.getMax() + ",sum:" + statistics.getSum() + ",average:" + statistics.getAverage());
模式匹配
/ 模式匹配,类似于Java的switch语法
val oper = '#'
val n1 = 20
val n2 = 10
var res = 0
oper match {
case '+' => res = n1 + n2
case '-' => res = n1 - n2
case '*' => res = n1 * n2
case '/' => res = n1 / n2
case _ => println("oper error")
}
println("res=" + res)
match的细节和注意事项
如果所有case都不匹配,那么执行case _ 分支,类似于Java中default语句
如果所有case都不匹配,又没有写case _ 分支,那么会抛出MatchError
每个case中,不用break语句,自动中断case
可以在match中使用其它类型,而不仅仅是字符,可以是表达式
=> 类似于 java swtich 的 :
=> 后面的代码块到下一个case, 是作为一个整体执行,可以使用{} 括起来,也可以不括。
如果在case前面加上变量那么就会将值赋值给他:
for(ch<-"1+!#")
{
ch match{
case "+"=>printf("+")
case res=>printf(res)
case_=>println("ok__")
}
}
模式匹配变量类型:
object Demo {
def main(args: Array[String]): Unit = {
val names = List(1,2,3,4,5)
var s=(1,"str",names)
val iterator = s.productIterator
for(tmp<-iterator)
{
tmp match{
case i:Int=>println("is int");
case _:List[Int]=>println("is list[int]")
case _=>println("other")
}
}
}
}
//输出结果为:
is int
other
is list[int]
匹配数组:
for (arr <- Array(Array(0), Array(1, 0), Array(0, 1, 0),
Array(1, 1, 0), Array(1, 1, 0, 1))) {
val result = arr match {
case Array(0) => "0"
case Array(x, y) => x + "=" + y
case Array(0, _*) => "以0开头和数组"
case _ => "什么集合都不是"
}
println("result = " + result)
}
其实通过这里可以推断出:匹配元组、匹配list的写法,无非是将case后面写成(x,y)就是匹配元组,将返回值赋值给x,y,写出0::Nil就是匹配list(0),当然我们也可以将模式匹配进行更深层次的抽象比如:
变量模式匹配:
var (x,y)=(1,2)// 变量的模式匹配
val map = Map("A"->1, "B"->0, "C"->3)
for((k->v)<-map)
{
printf(k+""+v)
}
样例类:
写法:
case class Demo(val:Double)
样例类仍然是类
样例类用case关键字进行声明。
样例类是为模式匹配(对象)而优化的类
构造器中的每一个参数都成为val——除非它被显式地声明为var
在样例类对应的伴生对象中提供apply方法让你不用new关键字就能构造出相应的对象
提供unapply方法让模式匹配可以工作
将自动生成toString、equals、hashCode和copy方法(有点类似模板类,直接给生成,供程序员使用)
除上述外,样例类和其他类完全一样。你可以添加方法和字段,扩展它们
高阶函数
偏函数:
就是只对部分数据进行处理类比如我们高数中的偏导数,只关心涉及到的
object Demo {
def main(args: Array[String]): Unit = {
val names = List(1,2,3,4,"lalal")
val parfun=new PartialFunction[Any,Int] {
override def isDefinedAt(x: Any): Boolean ={//第一个函数为判断是不是我们关心的类型,是返回true
return x.isInstanceOf[Int]
}
override def apply(v1: Any): Int = v1.asInstanceOf[Int]+2;//对关心数据的处理
}
val ints = names.collect(parfun)
println(ints)
//输出结果:
List(3, 4, 5, 6)
偏函数的简化:
def par:PartialFunction[Any,Int]={
case i;Int=>i+2
}
val list2 = List(1, 2, 3, 4,"ABC").collect(f2)
再次精简:
val list2 = List(1, 2, 3, 4,"ABC").collect(case i:Int=>i+2)