需求背景
用户登录之后将其云端收藏的内容同步到本地数据库且保持和原收藏顺序一致, 比如在电脑上登录之后显示的收藏顺序A->B->C 切换到手机登录之后的顺序预期也是A->B->C, 之后的查询就可以不依赖云端接口而是直接查本地数据库
代码抽象
针对这个场景我们抽象出来一段 伪代码
fun test() {
// list是云端服务器返回的数据 按照顺序 ABC
val list = mutableListOf<String>("A", "B", "C")
list.forEach{
// 本地数据库插入这条记录和 对应的更新时间, 以便后续查询的时候可以直接读取数据库
dao.insertItem(it,System.currentTimeMillis())
}
}
看起来没有什么问题吧? 插入一条就更新本条的时间戳~
实际上遇到了坑——时间戳重复
2023-07-30 23:11:12.601 9952-9952 A time = 1690729872601
2023-07-30 23:11:12.601 9952-9952 B time = 1690729872601
2023-07-30 23:11:12.601 9952-9952 C time = 1690729872601
数据库插入的操作执行地很快导致 多条记录在同一ms内执行, 当你再去查询数据库的收藏顺序时就无法保证一定是按照ABC返回的
解决办法
1 下标去重法 推荐指数 5颗星 ⭐️⭐️⭐️⭐️⭐️
val list = mutableListOf<String>("A", "B", "C")
val time = System.currentTimeMillis()
list.forEachIndexed { index, s ->
Log.i("TAG", "$s time = ${time + index}")
}
2023-07-30 23:21:13.927 11181-11181 A time = 1690730473927
2023-07-30 23:21:13.927 11181-11181 B time = 1690730473928
2023-07-30 23:21:13.927 11181-11181 C time = 1690730473929
2 延时去重法 推荐指数 1颗星 ⭐️
空耗cpu性能1ms 极端条件下考虑
fun test() {
val list = mutableListOf<String>("A", "B", "C")
list.forEachIndexed { index, s ->
Thread.sleep(1)
Log.i("TAG", "$s time = ${System.currentTimeMillis()}")
}
}
2023-07-30 23:29:01.444 11997-11997 A time = 1690730941444
2023-07-30 23:29:01.445 11997-11997 B time = 1690730941445
2023-07-30 23:29:01.446 11997-11997 C time = 1690730941446
3 纳秒去重法 推荐指数 2颗星 ⭐️⭐️
因为获取纳秒本身就是一个消耗性能的方式, 因此也不推荐
fun test() {
val list = mutableListOf<String>("A", "B", "C")
list.forEachIndexed { index, s ->
val nTime = System.nanoTime()
Log.i("TAG", "$s time = $nTime")
}
}
2023-07-30 23:26:30.382 11810-11810 A time = 1809472049499997
2023-07-30 23:26:30.382 11810-11810 B time = 1809472049659074
2023-07-30 23:26:30.382 11810-11810 C time = 1809472049687304
也可以从数据库的查询上考虑如何解决: 时间戳相同的情况下,如何自定义返回顺序。这个我还没有研究明白,欢迎大家补充。