我正在使用 Collections.sort(( 对列表进行排序,它似乎正在以各种方式对其进行测试。 不过,我的一些用户正在崩溃。
Caused by java.lang.UnsupportedOperationException
java.util.AbstractList.set (AbstractList.java:681)
java.util.AbstractList$FullListIterator.set (AbstractList.java:143)
java.util.Collections.sort (Collections.java:1909)
com.myapp.MyFragment.myMethod (MyFragment.java:225)
但是,我所做的只是尝试对列表进行排序
private void myMethod(List<MyThing> myThings) {
Collections.sort(myList, (thing1, thing2) -> Long.compare(thing2.getLongValue(), thing1.getLongValue()));
我注意到这在Android 8及更高版本上不会发生。它只发生在 5.0 - 7.1 上
该列表实例化为 ArrayList,填充,并设置为类实例的成员作为泛型列表。 然后,此对象与事件总线一起发布。 然后使用 Kotlin 的map
和sortedByDescending
函数对列表进行映射和排序。 然后将映射和排序的列表传递给myMethod()
这个 Kotlin 扩展正在生成传递给此方法的列表:
fun List<MyThing>.mapAndSort(context: Context): List<MyThing> {
return mapNotNull {
when (it.type) {
type -> it.getTyped(context) //all of these return polymorphic MyThings
anotherType -> it.getAnotherTyped(context)
someOtherType -> it.getSomeOtherTyped(context)
yetAnotherType -> it.getYetAnotherType(context)
yetOneMoreType -> it.getYetOneMoreType(context)
finallyLastTyope -> it.getFinallyLastType(context)
else -> null
}
}.sortedByDescending { it.longValue }
}
到目前为止,我已经看到这个列表是一个java.util.Arrays$ArrayList
,kotlin.collections.EmptyList
。
我认为这与 EventBus 有关,但可能是 Kotlin 传递了 Kotlin 集合列表类型。 有谁确切知道发生了什么?
Collections.sort
是一个就地列表突变操作。如果你打算在你的 Java 方法中调用它,只在那里传递一个静态已知的列表,它是 Kotlin 中的MutableList
。
如果你有一个未知可变性的List
,你可以通过调用它.toMutableList()
扩展函数来获取MutableList
。
如果用 Java 编写myMethod
不是主要的,你可以用 Kotlin 中的调用替换它list.sortedByDescending { it.longValue }
那么你就不需要先将该列表转换为可变列表。事实上,这就是mapAndSort
方法最终的作用,所以看起来没有必要再次排序。
这次崩溃的根源似乎是,在内部,如果Iterable
的大小为 0 或 1,Iterable<T>.sortedWith
(由 Iterable<T>.sortedByDescending
使用(会创建一个新列表:
public fun <T> Iterable<T>.sortedWith(comparator: Comparator<in T>): List<T> {
if (this is Collection) {
if (size <= 1) return this.toList() // <-- HERE
@Suppress("UNCHECKED_CAST")
return (toTypedArray<Any?>() as Array<T>).apply { sortWith(comparator) }.asList()
}
return toMutableList().apply { sortWith(comparator) }
}
函数toList()
依次调用listOf
:
public fun <T> Iterable<T>.toList(): List<T> {
if (this is Collection) {
return when (size) {
0 -> emptyList()
1 -> listOf(if (this is List) get(0) else iterator().next())
else -> this.toMutableList()
}
}
return this.toMutableList().optimizeReadOnlyList()
}
这反过来将解析为一个EmptyList
(可以安全排序,因为它是空的(或一个不实现set
的SingletonList
from AbstractList
以下是一些证据:
https://try.kotlinlang.org/#/UserProjects/s3j6g8476h8047vvvsjuvletlr/rjlkkn3n6117c1aagja8dr1h67
我们可能会遇到错误,或者至少是改进,因为如果它是 List
类型,sortedWith
可能会返回this
:
public fun <T> Iterable<T>.sortedWith(comparator: Comparator<in T>): List<T> {
if (this is Collection) {
if (size <= 1) return if(this is List<T>) this else this.toList()
@Suppress("UNCHECKED_CAST")
return (toTypedArray<Any?>() as Array<T>).apply { sortWith(comparator) }.asList()
}
return toMutableList().apply { sortWith(comparator) }
}