总结

  1. 即使kotlin将集合声明为只读的,java代码也可以直接进行修改
  2. java中的集合不区分只读和可修改,所以kotlin在处理java集合的时候,既可以当成是只读的,也可以当成是可修改的

只读集合与可变集合

kotlin 的集合设计和 Java 不同的另一项特性是:kotlin 把访问数据的接口和修改集合数据的接口分开了,kotlin.collections.Collection 接口提供了遍历集合元素、获取集合大小、判断集合是否包含某元素等操作,但这个接口没有提供添加和移除元素的方法。kotlin.collections.MutableCollection 接口继承于 kotlin.collections.Collection 接口,扩展出了用于添加、移除、清空元素的方法

集合元素 只读 可变
List listOf mutableListOf、arrayListOf
Set setOf mutableSetOf、hashSetOf、linkedSetOf、sortedSetOf
Map mapOf mutableMapOf、hashMapOf、linkedMapOf、sortedMapOf

集合与 Java

因为 Java 并不会区分只读集合与可变集合,即使 kotlin 中把集合声明为只读的, Java 代码也可以修改这个集合,而 Java 代码中的集合对 kotlin 来说也是可变性未知的,kotlin 代码可以将之视为只读的或者可变的,包含的元素也是可以为 null 或者不为 null 的
例如,在 Java 代码中 names 这么一个 List< String > 类型的变量

  1. public class JavaMain {
  2. public static List<String> names = new ArrayList<>();
  3. static {
  4. names.add("leavesC");
  5. names.add("Ye");
  6. }
  7. }

在 kotlin 中可以用以下四种方式来引用变量 names

val list1: List<String?> = JavaMain.names
val list2: List<String> = JavaMain.names
val list3: MutableList<String> = JavaMain.names
val list4: MutableList<String?> = JavaMain.names

解构与表达式

解构在简化语法上非常有用:

// 遍历 Map
for ((key, value) in mHashMap) {
// do something
}

当一个表达式或者函数要返回两个或两个以上的值的时候,解构也非常优雅:

val (color, backgrond) = if (isRed) {
    mRed to mRedBackground
} else {
    mGreen to mGreenBackground
}

Sequences

序列操作又被称之为惰性集合操作,Sequences序列接口强大在于其操作的实现方式。序列中的元素求值都是惰性的,所以可以更加高效使用序列来对数据集中的元素进行链式操作(映射、过滤、变换等),而不需要像普通集合那样,每进行一次数据操作,都必须要开辟新的内存来存储中间结果,而实际上绝大多数的数据集合操作的需求关注点在于最后的结果而不是中间的过程,

序列是在Kotlin中操作数据集的另一种选择,它和Java8中新增的Stream很像,在Java8中我们可以把一个数据集合转换成Stream,然后再对Stream进行数据操作(映射、过滤、变换等),序列(Sequences)可以说是用于优化集合在一些特殊场景下的工具。但是它不是用来替代集合,准确来说它起到是一个互补的作用。

中间和末端操作

序列操作分为两类:中间和末端。一次中间操作返回的是另一个序列,这个新序列知道如何变换原始序列中的元素。而一次末端操作返回的是一个结果
image.png

在使用集合函数比如mapfilter。这些函数会及早的创建中间集合,也就是说每一步的中间结果都被存储在一个临时列表。而序列给了你另一种选择,可以让你避免创建这些临时的中间对象。如下一个例子:

val peoples = listOf(Person("Alice",20),Person("Bob",31))
peoples.map(Person::name).filter { it.startsWith("A") }

上面的例子中mapfilter都会返回一个列表,也就是说链式的调用会创建两个列表,如果源列表中只有两个元素,这不是什么问题,但如果有一百万个元素,(链式)调用就会变得十分低效。
为提高效率,可以把操作变成使用序列,而不是直接使用集合

 peoples.asReversed() <!--把初始集合转换成序列-->
    .map ( People::name )  <!--序列支持和集合一样的API-->
    .filter {it.startsWith("A") }
    .toList() <!--把结果序列转换回列表-->

Kotlin惰性集合操作的入口就是Sequence接口,它的强大之处就在于其操作的实现方式,序列中元素的求值是惰性的。因此可以使用序列高效地对集合元素执行链式操作,而不需要创建额外的集合来保存过程中产生的中间结果。
可以调用扩展函数asSequence把任意集合转换成序列,调用toList来做反向的转换

作者:满天星爱我 链接:https://www.jianshu.com/p/99e164fbee51 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。