Android Kotlin函数式编程(II)

#Android函数式编程(II)#

前言

最近Kotlin 1.0正式版的发布,让Kotlin在众多开发者眼前一亮,越来越多的人开始着眼新的语言进行 学习,然而网上的文章多数是介绍Kotlin这门新语言的语法以及一些技术性细节,却发现鲜有讨论 Kotlin这门新语言带来的一些方便的函数式语言特性。翻译这篇文章的目的是,把Kotlin提供的内置的 一些函数式特性详细的展现出来,以便于我们用到这门语言的一些场景时可以适的用上这些特性,帮助增 强我们的代码。尽管Kotlin要大范围的使用,还有一段距离,但是这并不能阻挡我们学习新语言的新特 性的脚步。

原文来自:http://antonioleiva.com/collection-operations-kotlin/ Lambda表达式是一种在简化代码方面十分强有力的工具,而且有时候会做到过做不到的事情。我们在 系列第一部分 (Kotlin lambda表达式:释放函数蕴含的洪荒之力)中讨论了这些特性。

在上一部分结尾的时候的我们说,lambda表达式是用于实现函数式编程特性的基石,比如像我们今天要 讨论的特性:集合操作。Kotlin 提供了一些十分出色的操作方法,这些方法原本在那些不支持 lambda表达式中是无法用到(或者实现非常啰嗦)的。本文并不是特别在Android平台上实现的特性, 但是这些是可以多方面地增强Android应用的开发。现在我们就来讨论下Kotlin提供对不同类型集合的 那些操作。

集合

尽管我们可以仅仅使用Java提供的集合,但Kotlin也提供了一系列你一定想要的一些很好用的本地接口: - Iterable:(不可变)可遍历对象。可以作为一个父类,任何类继承这个接口可以获得对一个元素序列的遍历操作。 - MutableIterable: 可变可遍历对象。遍历时支持移除遍历条目的可遍历对象。 - Collection: (不可变)集合这个类代表一个通用的元素集合。我们可以使用一些提供的函数返回集合的大小,判断是否为空集,包含有一个元素还是多个元素。这个类型的集合都仅仅只能去请求读取数据,而不能操作数据,因为这种集合是不可变的。 - MutableCollection:可变集合。支持增加删除和添加操作的集合Collection。提供了一些额外可以操作数据的方法,例如add, remove, clear等等。 - List:列表:这可能是用的最多的的集合了。他代表一种有序的元素列表。因为它有序,我们可以通过位置索引来使用get函数请求特定位置上的元素。 - MutableList:可变列表:一个支持添加和移除元素的List列表。 - Map:键值对存储集合(映射)。一个映射中的键名应该是各自唯一的,不重复,也就是说在映射当中不会存在两个相同的键名。 - MutableMap:一个支持添加和移除元素的Map。

集合操作

接下来我们将会使用一些函数式操作来对不同的集合进行不同的操作。我会展示一些定义和示例。这对于了解这些可选的操作很有益,因为这是一种很易于了解这些函数使用场景的方式。

18.1 聚合操作

any 任一函数

如果至少有一个元素符合给定的谓词判断会返回true。

    val list = listOf(1, 2, 3, 4, 5, 6)
    assertTrue(list.any { it % 2 == 0 })
    assertFalse(list.any { it > 10 })

all 保全函数

如果所有的元素都符合给定的谓词判断会返回true。

    assertTrue(list.all { it < 10 })
    assertFalse(list.all { it % 2 == 0 })

count 计数函数

返回符合给定的谓词判断的元素数量

    assertEquals(3, list.count { it % 2 == 0 })

fold 左折叠函数

以一个初始值开始“积聚”操作,从集合中第一个元素到最后一个元素逐个应用该操作.

    assertEquals(25, list.fold(4) { total, next -> total + next })

foldRight 右折叠函数

功能同fold函数,但是顺序为从最后一个到第一个元素。

    assertEquals(25, list.foldRight(4) { total, next -> total + next })

forEach 逐一函数

为每一个元素执行给定的操作

    list forEach { println(it) }

forEachIndexed 索引化逐一函数

功能同forEach,不过我们可以连同索引值一同读出。

    list forEachIndexed { index, value 
            -> println("position $index contains a $value") }

max 最大值函数

返回最大值,如果如果没有元素返回null

    assertEquals(6, list.max())

maxBy 变形后最大值函数

返回得到给定函数操作元素值后的比较得到最大值的第一个元素,如果没有元素返回null

    // The element whose negative is greater
    assertEquals(1, list.maxBy { -it })

min 最小值函数

返回最小元素,如果没有元素返回null

        assertEquals(1, list.min())

minBy 变形后最小值函数 返回得到给定函数操作元素值后的比较得到最小值的第一个元素,如果没有元素返回null

    // The element whose negative is smaller
    assertEquals(6, list.minBy { -it })

none 无符合条件函数

    // No elements are divisible by 7
    assertTrue(list.none { it % 7 == 0 })

reduce 左化简函数

功能同fold左折叠函数,但是它没有初始值。它直接从集合中第一个元素开始积聚到最后一个元素。

    assertEquals(21, list.reduce { total, next -> total + next })

reduceRight 右化简函数

功能同reduce,但是顺序为从最后一个元素到第一个元素。

    assertEquals(21, list.reduceRight { total, next -> total + next })

sumBy 变形后求和函数

返回集合中元素变形后所有值的求和

    assertEquals(3, list.sumBy { it % 2 })

18.2 过滤操作

drop 抛弃函数

返回一个除去了前n项元素外所有元素的列表

       //去除了前4项
       assertEquals(listOf(5, 6), list.drop(4))

dropWhile 条件抛弃函数

返回一个除去了第一个符合给定谓词的条件的元素所剩下的所有元素的集合

    assertEquals(listOf(3, 4, 5, 6), list.dropWhile { it < 3 })

dropLastWhile 尾部元素条件抛弃函数

返回一个除去了尾部符合给定谓词的条件的元素所剩下的所有元素的集合

    assertEquals(listOf(1, 2, 3, 4), list.dropLastWhile { it > 4 })
    译者注:这两个函数从名称上和功能描述上具有高度的相似性,然而举的例子却
    无法构成有效对比,这两个例子给人的感觉就是:这俩函数功能这不是一样么?
    
    读者需要对这两个函数多多进行实验对比并验证功能。

filter 漏斗函数

返回所有符合给定的谓词描述的条件的所有元素

    assertEquals(listOf(2, 4, 6), list.filter { it % 2 == 0 })

filterNot 排除函数

返回所有不符合给定的谓词描述的条件的所有元素

    assertEquals(listOf(1, 3, 5), list.filterNot { it % 2 == 0 })

filterNotNull 去空函数

返回所有不为空的元素

    assertEquals(listOf(1, 2, 3, 4), listWithNull.filterNotNull())

slice 切片函数

返回包含了指定索引元素的列表。

    assertEquals(listOf(2, 4, 5), list.slice(listOf(1, 3, 4)))

take 取元函数

返回了一个包含前n项元素的列表

    assertEquals(listOf(1, 2), list.take(2))

takeLast 取尾函数

返回了一个包含后n项元素的列表

assertEquals(listOf(5, 6), list.takeLast(2))

takeWhile 条件取元函数

返回一个包含符合给定的谓词条件的元素

        assertEquals(listOf(1, 2), list.takeWhile { it < 3 })

18.3 Map操作

flatMap 展平函数

首先为迭代每一个元素并逐一执行操作然后创建新的集合,最终将所有集合中所有的元素展平存放到一个单独的列表中。

    assertEquals(listOf(1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7),
                        list.flatMap { listOf(it, it + 1) })

groupBy 分组函数

用给定的函数为原始的集合当中的元素分组,最后分别返回分组后的映射。

assertEquals(mapOf("odd" to listOf(1, 3, 5), "even" to listOf(2, 4, 6)),
            list.groupBy { if (it % 2 == 0) "even" else "odd" })

map 分摊处理函数

原集合当中每一项元素都通过应用给定的函数变形后,新的元素作为一个列表返回。

assertEquals(listOf(2, 4, 6, 8, 10, 12), list.map { it * 2 })

mapIndexed 分摊索引处理函数

为原集合当中每一个元素和元素的索引值通过给定的函数变形后,所有新的元素作为列表返回。

assertEquals(listOf (0, 2, 6, 12, 20, 30), list.mapIndexed { index, it
        -> index * it })

mapNotNull 非空分摊处理函数

返回一个包含了每一个原集合中应用了给定变形的函数的非空元素的结果列表。

assertEquals(listOf(2, 4, 6, 8), listWithNull mapNotNull { it * 2 })

18.4 通用元素操作

contains 包含于函数

如果在集合中找到指定元素返回true。

assertTrue(list.contains(2))

elementAt 索引取元函数

返回一个给定索引位置上的元素,如果索引超出集合范围,会抛出IndexOutOfBoundsException索引越界异常。

assertEquals(2, list.elementAt(1))

elementAtOrElse 备选元索引取元函数

返回一个给定索引位置上的元素,如果索引超出集合范围,则返回调用默认函数的结果。

assertEquals(20, list.elementAtOrElse(10, { 2 * it }))

elementAtOrNull 索引取元函数

返回一个给定索引位置上的元素,如果索引超出集合范围,则返回null。

assertNull(list.elementAtOrNull(10))

first 条件首元函数

返回符合给定谓词条件的第一个元素。

assertEquals(2, list.first { it % 2 == 0 })

firstOrNull 条件首元函数

返回符合给定谓词条件的第一个元素,如果找不到符合的元素,返回null。

assertNull(list.firstOrNull { it % 7 == 0 })

indexOf 取索引函数

Returns the first index of element, or -1 if the collection does not contain element. 返回元素在集合中的第一个索引,如果集合不存在该元素,返回-1。

assertEquals(3, list.indexOf(4))

indexOfFirst 条件取首索引函数

返回符合给定的谓词条件的第一个元素的索引,如果集合没有符合条件的元素,则返回-1。

assertEquals(1, list.indexOfFirst { it % 2 == 0 })

indexOfLast 条件取尾索引函数

返回符合给定的谓词条件的最末尾元素的索引,如果集合没有符合条件的元素,则返回-1。

assertEquals(5, list.indexOfLast { it % 2 == 0 })

last 条件取尾函数

返回符合给定的谓词条件的最末尾元素。

assertEquals(6, list.last { it % 2 == 0 })

lastIndexOf 取尾索引函数

Returns last index of element, or -1 if the collection does not contain element. 返回给定元素在集合中的最后一个索引,如果集合中不存在该元素,返回-1。

val listRepeated = listOf(2, 2, 3, 4, 5, 5, 6)
assertEquals(5, listRepeated.lastIndexOf(5))

**译者注**:indexOfLast请一定要和lastIndexOf区分清楚,单词很相像,但它们不一样,前者通过一个匿名函数体设定过滤元素的条件,再取出符合条件的最后一个元素,后者是通过元素取出该元素在集合当中(或有重复项)最后一个该元素的位置索引。

lastOrNull 条件取尾函数

Returns the last element matching the given predicate, or null if no such element was found.

返回符合给定的谓词条件的最末尾元素,如果不存在符合条件的元素会返回null。

val list = listOf(1, 2, 3, 4, 5, 6)
assertNull(list.lastOrNull { it % 7 == 0 })

single 单结果函数

返回一个且仅有一个符合给定的谓词条件的元素,如果没有符合条件的元素或有超过一个元素符合条件,将会抛出异常。

assertEquals(5, list.single { it % 5 == 0 })

singleOrNull 单结果函数

返回一个且仅有一个符合给定的谓词条件的元素,如果没有符合条件的元素或有超过一个元素符合条件,将会返回null。

assertNull(list.singleOrNull { it % 7 == 0 })