You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
接下来的 Task,都是围绕集合展开的,Kotlin 的集合和 Java 的集合差不多,不过 Kotlin 扩展了许多有用的方法。我们先看一下 Show 类的定义:
data class Shop(val name: String, val customers: List<Customer>)
data class Customer(val name: String, val city: City, val orders: List<Order>) {
override fun toString() = "$name from ${city.name}"
}
data class Order(val products: List<Product>, val isDelivered: Boolean)
data class Product(val name: String, val price: Double) {
override fun toString() = "'$name' for $price"
}
data class City(val name: String) {
override fun toString() = name
}
比较容易,直接用 Shop 中的 customers 转换成 Set 就可以了:
Task 21:Filter; map
其中我们可以看到 map 方法是:对于给定的规则,返回 List:
/**
* Returns a list containing the results of applying the given [transform] function
* to each element in the original collection.
*/
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}
/**
* Applies the given [transform] function to each element of the original collection
* and appends the results to the given [destination].
*/
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C {
for (item in this)
destination.add(transform(item))
return destination
}
/**
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
return filterTo(ArrayList<T>(), predicate)
}
/**
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterTo(destination: C, predicate: (T) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
return destination
}
Task 22:All, Any and other predicates
有了上面的经验,这里的问题就好解决了:
根据名称,我们其实可以很容易猜到是干什么,但是我们这里还是要看看其中具体是怎么实现的:
/**
* Returns `true` if all elements match the given [predicate].
*/
public inline fun <T> Iterable<T>.all(predicate: (T) -> Boolean): Boolean {
if (this is Collection && isEmpty()) return true
// 有一个不符合条件,就返回 false
for (element in this) if (!predicate(element)) return false
return true
}
/**
* Returns `true` if at least one element matches the given [predicate].
*/
public inline fun <T> Iterable<T>.any(predicate: (T) -> Boolean): Boolean {
if (this is Collection && isEmpty()) return false
// 有符合条件的,就返回 true
for (element in this) if (predicate(element)) return true
return false
}
/**
* Returns the number of elements matching the given [predicate].
*/
public inline fun <T> Iterable<T>.count(predicate: (T) -> Boolean): Int {
if (this is Collection && isEmpty()) return 0
var count = 0
// 有符合条件的,计数加一,最后返回计数
for (element in this) if (predicate(element)) count++
return count
}
/**
* Returns the first element matching the given [predicate], or `null` if no such element was found.
*/
@kotlin.internal.InlineOnly
public inline fun <T> Iterable<T>.find(predicate: (T) -> Boolean): T? {
return firstOrNull(predicate)
}
/**
* Returns the first element matching the given [predicate], or `null` if element was not found.
*/
public inline fun <T> Iterable<T>.firstOrNull(predicate: (T) -> Boolean): T? {
// 有符合条件的,返回符合条件的这一项
for (element in this) if (predicate(element)) return element
return null
}
Task 23:FlatMap
FlatMap 对集合中的元素去重组成新的集合:
/**
* Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original collection.
*/
public inline fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R> {
return flatMapTo(ArrayList<R>(), transform)
}
/**
* Appends all elements yielded from results of [transform] function being invoked on each element of original collection, to the given [destination].
*/
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.flatMapTo(destination: C, transform: (T) -> Iterable<R>): C {
// 遍历集合中元素,把元素的去重后重组成 List 返回
for (element in this) {
val list = transform(element)
destination.addAll(list)
}
return destination
}
Task 24:Max; min
最大最小的查找是比较常用的操作,结合前面的 FlatMap,可以解决此问题:
其中我们看看 max 是如何实现的:
/**
* Returns the first element yielding the largest value of the given function or `null` if there are no elements.
*/
public inline fun <T, R : Comparable<R>> Iterable<T>.maxBy(selector: (T) -> R): T? {
val iterator = iterator()
if (!iterator.hasNext()) return null
var maxElem = iterator.next()
var maxValue = selector(maxElem)
// 简单粗暴遍历查找符合条件的最大的一项,是稳定的
while (iterator.hasNext()) {
val e = iterator.next()
val v = selector(e)
if (maxValue < v) {
maxElem = e
maxValue = v
}
}
return maxElem
}
Task 24:Sort
排序:
看似简单,不过似乎有没那么简单:
/**
* Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function.
*/
public inline fun <T, R : Comparable<R>> Iterable<T>.sortedBy(crossinline selector: (T) -> R?): List<T> {
return sortedWith(compareBy(selector))
}
/**
* Returns a list of all elements sorted according to the specified [comparator].
*/
public fun <T> Iterable<T>.sortedWith(comparator: Comparator<in T>): List<T> {
if (this is Collection) {
if (size <= 1) return this.toList()
@Suppress("UNCHECKED_CAST")
return (toTypedArray<Any?>() as Array<T>).apply { sortWith(comparator) }.asList()
}
return toMutableList().apply { sortWith(comparator) }
}
/**
* Creates a comparator using the function to transform value to a [Comparable] instance for comparison.
*/
@kotlin.internal.InlineOnly
public inline fun <T> compareBy(crossinline selector: (T) -> Comparable<*>?): Comparator<T> =
Comparator { a, b -> compareValuesBy(a, b, selector) }
/**
* Compares two values using the specified [selector] function to calculate the result of the comparison.
* The function is applied to the given values [a] and [b] and return [Comparable] objects.
* The result of comparison of these [Comparable] instances is returned.
*/
@kotlin.internal.InlineOnly
public inline fun <T> compareValuesBy(a: T, b: T, selector: (T) -> Comparable<*>?): Int {
return compareValues(selector(a), selector(b))
}
/**
* Compares two nullable [Comparable] values. Null is considered less than any value.
*/
public fun <T : Comparable<*>> compareValues(a: T?, b: T?): Int {
if (a === b) return 0
if (a == null) return -1
if (b == null) return 1
@Suppress("UNCHECKED_CAST")
return (a as Comparable<Any>).compareTo(b)
}
/**
* Returns a list of all elements sorted according to the specified [comparator].
*/
public fun <T> Iterable<T>.sortedWith(comparator: Comparator<in T>): List<T> {
if (this is Collection) {
if (size <= 1) return this.toList()
@Suppress("UNCHECKED_CAST")
return (toTypedArray<Any?>() as Array<T>).apply { sortWith(comparator) }.asList()
}
return toMutableList().apply { sortWith(comparator) }
}
Task 25:Sum
求和:
/**
* Returns the sum of all values produced by [selector] function applied to each element in the collection.
*/
public inline fun <T> Iterable<T>.sumByDouble(selector: (T) -> Double): Double {
var sum: Double = 0.0
// 遍历并相加
for (element in this) {
sum += selector(element)
}
return sum
}
Task 26:Group By
分组:
实现方法:
/**
* Groups elements of the original collection by the key returned by the given [keySelector] function
* applied to each element and returns a map where each group key is associated with a list of corresponding elements.
*
* The returned map preserves the entry iteration order of the keys produced from the original collection.
*
* @sample samples.collections.Collections.Transformations.groupBy
*/
public inline fun <T, K> Iterable<T>.groupBy(keySelector: (T) -> K): Map<K, List<T>> {
return groupByTo(LinkedHashMap<K, MutableList<T>>(), keySelector)
}
/**
* Groups elements of the original collection by the key returned by the given [keySelector] function
* applied to each element and puts to the [destination] map each group key associated with a list of corresponding elements.
*
* @return The [destination] map.
*
* @sample samples.collections.Collections.Transformations.groupBy
*/
public inline fun <T, K, M : MutableMap<in K, MutableList<T>>> Iterable<T>.groupByTo(destination: M, keySelector: (T) -> K): M {
for (element in this) {
val key = keySelector(element)
// 将新数据添加到 Map 中,如果以前有 Key,添加,否则创建后添加
val list = destination.getOrPut(key) { ArrayList<T>() }
list.add(element)
}
return destination
}
/**
* Returns the value for the given key. If the key is not found in the map, calls the [defaultValue] function,
* puts its result into the map under the given key and returns it.
*
* @sample samples.collections.Maps.Usage.getOrPut
*/
public inline fun <K, V> MutableMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
val value = get(key)
// 在 Map 中根据 Key 判断是否可以找到 Value,如果找不到,在这个 Map 中创建一条
return if (value == null) {
val answer = defaultValue()
put(key, answer)
answer
} else {
value
}
}
Task 27:Partition
区分(满足条件和不满住条件):
/**
* Splits the original collection into pair of lists,
* where *first* list contains elements for which [predicate] yielded `true`,
* while *second* list contains elements for which [predicate] yielded `false`.
*/
public inline fun <T> Iterable<T>.partition(predicate: (T) -> Boolean): Pair<List<T>, List<T>> {
val first = ArrayList<T>()
val second = ArrayList<T>()
// 判断是否满足条件,分别放到第一个第二个参数中
for (element in this) {
if (predicate(element)) {
first.add(element)
} else {
second.add(element)
}
}
return Pair(first, second)
}
/**
* Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each element.
*/
public inline fun <T, R> Iterable<T>.fold(initial: R, operation: (acc: R, T) -> R): R {
var accumulator = initial
for (element in this) accumulator = operation(accumulator, element)
return accumulator
}
继续接着上一篇我们介绍的,我们继续深入学习 Kotlin Koans。
Task 20:Introduction
接下来的 Task,都是围绕集合展开的,Kotlin 的集合和 Java 的集合差不多,不过 Kotlin 扩展了许多有用的方法。我们先看一下 Show 类的定义:
比较容易,直接用 Shop 中的 customers 转换成 Set 就可以了:
Task 21:Filter; map
其中我们可以看到 map 方法是:对于给定的规则,返回 List:
对于 filter 方法是:返回符合给定规则的 List,规则用于判定该元素是否符合要求,规则返回值为 Boolean
Task 22:All, Any and other predicates
有了上面的经验,这里的问题就好解决了:
根据名称,我们其实可以很容易猜到是干什么,但是我们这里还是要看看其中具体是怎么实现的:
Task 23:FlatMap
FlatMap 对集合中的元素去重组成新的集合:
Task 24:Max; min
最大最小的查找是比较常用的操作,结合前面的 FlatMap,可以解决此问题:
其中我们看看 max 是如何实现的:
Task 24:Sort
排序:
看似简单,不过似乎有没那么简单:
Task 25:Sum
求和:
Task 26:Group By
分组:
实现方法:
Task 27:Partition
区分(满足条件和不满住条件):
Task 28:Fold
聚合(Fold),思路是:找出所有商品,将这些商品依次和每一个用户买过的商品做交集,最后剩下的商品就是所有用户都购买了的商品:
小结
到这里,我们完成了集合类相关的测试,我们可以看到,集合的基本数据结构,Kotlin 和 Java 区别不大,但是 Kotlin 扩展了集合的方法,这些方法的灵活应用,可以基本满足平时集合相关的操作。要想更灵活的应用,需要我们多加练习,更好的去熟悉。
如果有一天你觉得过的舒服了,你就要小心了!欢迎关注我的公众号:我是任玉琢
The text was updated successfully, but these errors were encountered: