一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情。
reified
项目中我们经常遇到将一个list的Json字符串转换成List对象,每次传写object : TypeToken<ArrayList<T>>(){}.type,确实有点繁琐,我们可以定义一个扩展函数
fun <T> String.toTypedArray():ArrayList<T>{
return Gson().fromJson(this, object : TypeToken<ArrayList<T>>() {}.type)
}
这样就可以直接json.toTypedArray()获取转换的结果
val users = mutableListOf<User>()
users.add(User("张三",20))
users.add(User("李四",21))
val array = Gson().toJson(users).toTypedArray<User>()
运行之后会发现并没有那么简单,最后List里面存的不是我们需要的User对象,而是LinkedTreeMap,
这是由于Java泛型在运行时会被类型擦除,如何解决这个问题呢?就需要用到reified。
reified是kotlin提供的一个关键字,意在具体化泛型,它必须结合inline使用。因为内联函数在编译期间会吧字节码拷贝到调用它的地方,所以编译器就会知道当前方法中的泛型对应的具体类型是什么,修改下扩展函数
inline fun <reified T> String.toTypedArray():ArrayList<T>{
return Gson().fromJson(this, object : TypeToken<ArrayList<T>>() {}.type)
}
这时候在调用数据就正常了
Sequences
在项目中,我们经常会对数据集进行处理,对于List,kotlin给我们提供了很多方便的api,比如filter,map等,
这些操作符的实现也比较简单
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
return filterTo(ArrayList<T>(), predicate)
}
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}
可以看到,无论是filter还是map,他们都使通过创建一个新的ArrayList用来接受符合结果的数据,然后返回这个新的列表,这意味着调用一次这些api就会创建新的对象,如果在同一时间大量调用的话,就会引起内存暴涨,频繁GC,所以kotlin提供了序列(Sequences)来优化集合(List)在一些场景的缺陷。
Sequences操作被称之为惰性操作,因为他的中间操作不会创建临时对象,而是返回一个序列(Sequences),只有执行到末端操作的时候才会进行计算
判断一个操作符是不是末端操作符也很简单,看返回值是不是一个序列就可以了,如果是的话就说明这个操作符是中间操作符,否则就是末端操作符。
集合转序列很简单,直接调用asSequencef()方法就可以了,操作用到的api也和集合类似。
//集合
val count1 = users
.filter { it.age > 0 }
.map { "${it.name} ${it.age}" }
.count()
//序列
val count2 = users.asSequence()
.filter { it.age > 0 }
.map { "${it.name} ${it.age}" }
.count()