在列表上调用.sort时AbstractList UnsupportedOperationException [英] AbstractList UnsupportedOperationException when calling .sort on a List

查看:104
本文介绍了在列表上调用.sort时AbstractList UnsupportedOperationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Collections.sort()对列表进行排序,这似乎在我可以对其进行测试的所有方式中都可以正常工作.我的一些用户崩溃了.

I'm sorting a List using Collections.sort(), which seems to be working every way I can test it. Some of my users are crashing though.

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)

但是,我正在做的就是尝试对列表进行排序

But, all I'm doing is trying to sort a List

private void myMethod(List<MyThing> myThings) {

    Collections.sort(myList, (thing1, thing2) -> Long.compare(thing2.getLongValue(), thing1.getLongValue()));

我注意到这在Android 8及更高版本上不会发生.它仅发生在5.0-7.1

I'm noticing this doesnt happen on Android 8 and above. Its only happening on 5.0 - 7.1

该列表实例化为ArrayList,进行填充,并设置为作为通用列表的类的实例的成员.然后将该对象与EventBus一起发布.然后使用Kotlin的mapsortedByDescending函数对列表进行映射和排序.然后将映射和排序的列表传递给myMethod()

The list is instantiated as an ArrayList, populated, and set as a member of an instance of a class as a generic list. This object is then posted with EventBus. The list is then mapped and sorted using Kotlin's map and sortedByDescending functions. The mapped and sorted list is then passed to myMethod()

此Kotlin扩展程序正在生成传递给此方法的列表:

This Kotlin extension is generating the list passed to this method:

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$ArrayListkotlin.collections.EmptyList.

So far I've seen this list be a java.util.Arrays$ArrayList, and kotlin.collections.EmptyList.

我认为这与EventBus有关,但可能是Kotlin传递了Kotlin收藏夹列表类型.有谁确切地知道发生了什么事?

I'm thinking this has something to do with EventBus, but may be Kotlin passing a Kotlin collections list type. Does anyone know exactly what's going on?

推荐答案

此崩溃的根源似乎是在内部,Iterable<T>.sortedWith(由Iterable<T>.sortedByDescending使用的)创建了一个新列表,如果Iterable是0或1:

The source of this crash seems to be that, internally, Iterable<T>.sortedWith (which is used by Iterable<T>.sortedByDescending) creates a new list if the size of the Iterable is 0 or 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,而该SingletonList无法实现AbstractList

Which in turn will resolve into either an EmptyList (which is safe to sort since it's empty) or a SingletonList which doesn't implement set from AbstractList

以下是一些证据:

https://try.kotlinlang.org/#/UserProjects/s3j6r1v1hr1vr1nrv1hr1vr1c1v1c1v1c1v1c1v1v

我们可能有一个错误,或者至少是一个改进,因为如果sortedWith的类型为List,则它可能返回this:

We could potentially have a bug or, at least, an improvement since sortedWith could return this if it's of type 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) }
}

这篇关于在列表上调用.sort时AbstractList UnsupportedOperationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆