有趣的Scala列表

Scala的列表结构可以理解为一个样例类,因为它不需要使用new方法,例如:

scala> val a = List("a","b","c")
a: List[String] = List(a, b, c)

除了这种方法构建列表外,还可以使用::符号构建

scala> val t = "a" :: "b" :: "c" :: Nil
t: List[String] = List(a, b, c)

其中Nil表示空列表,::符号表示在列表前面追加元素,所以如果没有后面的Nil,Scala就会报错。

scala> val t = "a"::"b"::"c"
<console>:7: error: value :: is not a member of String
       val t = "a"::"b"::"c"

列表不同于数组Array,它是链表结构。并且列表元素必须要是同样的类型,如果列表里混用其它类型,那么它们的类型默认为Any类。所有类型的父类。

scala> val b = List("a",'b')
b: List[Any] = List(a, b)

有趣的一点在于,如果类型S是类型T的子类,那么List[S]也是List[T]的子类。这也是为什么下面的例子可以成立,因为空列表List[Nothing]是所有类型的子类,那么也是List[T]的子类型。

scala> val c:List[Int] = List()
c: List[Int] = List()
scala> List()
res5: List[Nothing] = List()

Scala的列表核心是三个方法:head(返回首元素),tail(除首元素以外的元素),isEmpty(判断是否为空)。

scala> val a = List(1,2,3)
a: List[Int] = List(1, 2, 3)
scala> a.head
res0: Int = 1
scala> a.tail
res1: List[Int] = List(2, 3)
scala> a.isEmpty
res2: Boolean = false

Scala的列表可以利用模式匹配实现和Python一样的解包

scala> val t = List(1,2,3)
t: List[Int] = List(1, 2, 3)
scala> val List(a,b,c) = t
a: Int = 1
b: Int = 2
c: Int = 3
scala> a
res3: Int = 1
scala> b
res4: Int = 2
scala> c
res5: Int = 3

当然如果你不确定元素数量的话,可以利用列表构建符号::去匹配元素,没有匹配上的元素都会变成列表赋给rest。

scala> val t = List(1,2,3,4)
t: List[Int] = List(1, 2, 3, 4)
scala> val a::b::rest = t
a: Int = 1
b: Int = 2
rest: List[Int] = List(3, 4)

下面聊下Scala列表的初阶方法和高阶方法,两者的区别仅在于初阶方法不接受函数作为参数传入,高阶可以。

  • 列表的拼接,使用:::符号
scala> val a = List(1,2,3)
a: List[Int] = List(1, 2, 3)
scala> val b = List(4,5,6)
b: List[Int] = List(4, 5, 6)
scala> a ::: b
res0: List[Int] = List(1, 2, 3, 4, 5, 6)

用模式匹配去看待列表拼接可以理解为:

scala> def concat[T](x:List[T],y:List[T]):List[T] =
     | x match {
     | case List() => y
     | case x :: xs => x :: concat(xs,y)
     | }
concat: [T](x: List[T], y: List[T])List[T]
scala> concat(a,b)
res2: List[Int] = List(1, 2, 3, 4, 5, 6)

只不过这里的concat定义的是函数,而不是列表的中缀方法。

  • 对应head和tail方法,还用init和last方法 init方法返回除末尾元素外的列表,last返回最后一个元素,显然对于链表结构,它们的运算量都是O(n)级别的
scala> a.init
res3: List[Int] = List(1, 2)
scala> a.last
res4: Int = 3
  • map、foreach,filter map函数很出名了,对列表每个元素做处理
scala> a.map(_+3)
res5: List[Int] = List(4, 5, 6)

foreach和map很类似,不过需要传入的是返回为Unit的函数

scala> var sum = 0
sum: Int = 0

scala> a.foreach(sum += _)

scala> sum
res7: Int = 6

filter则是过滤元素

scala> a.filter(_<2)
res8: List[Int] = List(1)

本文分享自微信公众号 - 鸿的学习笔记(shujuxuexizhilu)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-05-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java一日一条

浅谈Java中的equals和==

为什么第3行和第4行的输出结果不一样?==和equals方法之间的区别是什么?如果在初学Java的时候这个问题不弄清楚,就会导致自己在以后编写代码时出现一些低级...

7520
来自专栏猿人谷

const用法小结

常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。因此,定义或说明常类型时必须进行初始化。 概述 1. const有什么...

20370
来自专栏数据结构与算法

05:输出亲朋字符串

05:输出亲朋字符串 总时间限制: 1000ms 内存限制: 65536kB描述 编写程序,求给定字符串s的亲朋字符串s1。  亲朋字符串s1定义如下:给定...

48960
来自专栏V站

PHP常用系统内置函数,收藏以后别折磨自己写函数类了

16690
来自专栏静默虚空的博客

Java正则速成秘籍(二)之心法篇

导读 正则表达式是什么?有什么用? 正则表达式(Regular Expression)是一种文本规则,可以用来校验、查找、替换与规则匹配的文本。 又爱又恨的正...

207100
来自专栏Java帮帮-微信公众号-技术文章全总结

String中的null,以及String s;等区别详解

1、判断一个引用类型数据是否null。 用==来判断。 2、释放内存,让一个非null的引用类型变量指向null。这样这个对象就不再被任何对象应用了。等待JVM...

39940
来自专栏Java大联盟

Java基础之String

16910
来自专栏用户3030674的专栏

java抽象类和抽象方法之间的关系

抽象类和抽象方法之间的关系 有抽象方法的类,一定是抽象类;抽象类不一定有抽象方法 当子类继承抽象类时,必须要将抽象类中的抽象方法全部实现(或者称为重写),否则子...

15310
来自专栏编程

Python基础知识2:字典

字典一种key - value 的数据类型,就像上学用的字典通过拼音查找汉字一样;字典是Python语言中唯一的映射类型。字典对象是可变的,它是一个容器类型,能...

267100
来自专栏微信公众号:Java团长

浅谈Java中的equals和==

  为什么第4行和第5行的输出结果不一样?==和equals方法之间的区别是什么?如果在初学Java的时候这个问题不弄清楚,就会导致自己在以后编写代码时出现一些...

9810

扫码关注云+社区

领取腾讯云代金券