为什么在Java中使用比较器进行排序时,collections.sort会抛出不支持的操作异常?

46

以下是我用来按预定义顺序排序列表的代码。预定义顺序在itemsSorted列表中提到。

final List<String> itemsSorted = myMethod.getSortedItems();

List<String> plainItemList = myMethod2.getAllItems();

final Comparator<String> comparator = new Comparator<String>() {        

    public int compare(String str1, String str2) {
        return orderOf(str1) - orderOf(str2);
    }

    private int orderOf(String name) {          
        return ((itemsSorted)).indexOf(name);
    }
 };
 Collections.sort(plainItemList, comparator);
 return plainItemList;

上面的代码会抛出异常

Caused by: java.lang.UnsupportedOperationException
    at java.util.Collections$UnmodifiableList$1.set(Collections.java:1244)
    at java.util.Collections.sort(Collections.java:221)

我不确定为什么该列表是不可修改的,请帮助解答。


2
那么... myMethod2.getAllItems() 返回什么?您需要提供足够的信息来帮助我们。我们无法看到您的代码。 - Dave Newton
这取决于列表是如何创建的。请展示 myMethod2.getAllItems() 的代码。 - Marco Bolis
1
这个 Collections$ UnmodifiableList $1 不是很熟悉吗? - m0skit0
1
然后Cassandra将返回给您一个不可修改的列表。 - Marco Bolis
1
为什么要使用不可变列表?https://dev59.com/AWQn5IYBdhLWcg3wXGKr - m0skit0
显示剩余2条评论
1个回答

98

很明显,您的客户端方法创建了一个不可修改的列表(例如使用Collections#unmodifiableList等)。在排序之前,只需创建一个可修改的列表:

List<String> modifiableList = new ArrayList<String>(unmodifiableList);
Collections.sort(modifiableList, comparator);

2
Arrays.asList总是可修改的。它只是不可调整大小的。 - Kumar Abhinav
2
@qqilihq 我只是好奇你的看法 - 这个 UnsupportedOperationException 不是 Collections 的糟糕设计和违反 SOLID 原则(即 Liskov 替换原则)的例子吗?直到运行时才会出现问题。Collections.sort 只期望 List 接口,但在某些实现上会出现问题。这个就地排序的想法不是一个整体上的坏主意吗?更清晰的方法是返回已排序的 Iterable,你认为呢? - Varvara Kalinina
1
@VarvaraKalinina 我倾向于同意。例如,C#(afaik?)有一个明确的ImmutableList类型。我认为在Java中可以通过第三方库获得类似的构造,但与现有API的互操作性当然会很差。在我看来,Iterable只会让事情稍微好一点,因为Iterator又有一个remove方法,这将允许修改(这意味着最终该方法将再次抛出UnsupportedOperationException以表示它不允许修改)。 - qqilihq
1
@qqilihq 我之前有一些 C# 的背景,现在转到了 Java。相比于 C# 的 LINQ 和基本集合,Java 的集合接口有时候感觉像是一个醉汉写的。为什么 Iterator 会有 remove 方法呢?C# 的 Enumerator 可没有这个方法。 - Varvara Kalinina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接