我正在使用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,被填充,并被设置为作为通用列表的类的实例的成员。然后将该对象与EventBus一起发布。然后使用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收藏列表类型。有谁确切地知道发生了什么事?
答案 0 :(得分:5)
Collections.sort
是就地列表变异操作。如果要在Java方法中调用它,请仅传递在Kotlin中静态已知为MutableList
的列表。
如果您有List
未知的可变性,则可以通过在其上调用MutableList
扩展函数来从中获得.toMutableList()
。
如果用Java编写myMethod
对您来说不是主要的,您可以在Kotlin中用list.sortedByDescending { it.longValue }
调用替换它,那么您无需先将该列表变成可变列表。实际上,这就是mapAndSort
方法的最终结果,因此看起来好像不需要再次对其进行排序。
答案 1 :(得分:1)
此崩溃的原因似乎是,内部Iterable<T>.sortedWith
(Iterable<T>.sortedByDescending
使用)Iterable
的大小为0或1时创建了一个新列表:
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
(由于为空,因此可以安全地进行排序)或SingletonList
,它不能从set
实现AbstractList
< / p>
以下是一些证据:
https://try.kotlinlang.org/#/UserProjects/s3j6g8476h8047vvvsjuvletlr/rjlkkn3n6117c1aagja8dr1h67
由于sortedWith
的类型为this
,List
可能返回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) }
}
,因此我们可能会遇到错误或至少有所改进:
Shared Sub New()
'Await setAllAccountsAsync()
SetAllAccounts()
End Sub