42

Following is my code used to sort a list with predefined order. Defined order is mentioned in itemsSorted list.

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;

The above code throws

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

I'm not sure why the list is unmodifiable. Please help me on this.

Purushotham
  • 3,770
  • 29
  • 41
Poppy
  • 2,902
  • 14
  • 51
  • 75
  • 2
    So... what does `myMethod2.getAllItems()` return? You need to provide enough information to help. We cannot see your code. – Dave Newton Feb 18 '14 at 12:50
  • It depends on how the list is created. Show us the code of `myMethod2.getAllItems()` – Marco Bolis Feb 18 '14 at 12:50
  • Please show the code where you create the plainItemList. – piet.t Feb 18 '14 at 12:51
  • the plainItemList is a response got from Cassandra DB. ResultSet results = execute CQL query; if(results!=null){ for (Row row : results) { plainItemList= row.getList("itemList", String.class); } } – Poppy Feb 18 '14 at 12:52
  • 1
    Doesn't this Collections$ **UnmodifiableList** $1 ring a bell? – m0skit0 Feb 18 '14 at 12:53
  • 1
    then Cassandra is returning you an unmodifiable list – Marco Bolis Feb 18 '14 at 12:53
  • 1
    Why immutable list? http://stackoverflow.com/questions/16891659/how-does-concurrency-using-immutable-persistent-types-and-data-structures-work – m0skit0 Feb 18 '14 at 12:55

1 Answers1

93

The list is not modifiable, obviously your client method is creating an unmodifiable list (using e.g. Collections#unmodifiableList etc.). Simply create a modifiable list before sorting:

List<String> modifiableList = new ArrayList<String>(unmodifiableList);
Collections.sort(modifiableList, comparator);
qqilihq
  • 10,794
  • 7
  • 48
  • 89
  • 2
    Arrays.asList is always modifiable.It is only not resizable – Kumar Abhinav Feb 18 '14 at 13:04
  • 2
    @qqilihq I'm just curious about your opinion - isn't this UnsupportedOperationException an example of bad design of `Collections` and breaking SOLID principles (namely, Liskov substitaution principle). Nothing breaks until runtime. `Collections.sort` expects just `List` interface, while it breaks on certain implementations. Isn't this sort-in-place thing an overall bad idea and a cleaner approach would be returning sorted `Iterable`, do you think? – Varvara Kalinina Feb 14 '19 at 09:11
  • 1
    @VarvaraKalinina I tend to agree. E.g. C# (afaik?) has an explicit ImmutableList type. I think similar constructs are available via 3rd party libs in Java, but interoperability with existing APIs will of course be bad. Imho an `Iterable` would make things only a little better, as `Iterator` again has a `remove` method, which would allow modifications (which means, at the end this method will have to throw an `UnsupportedOperationException` again to signal that it doesn't allow modifications). – qqilihq Feb 14 '19 at 10:56
  • 1
    @qqilihq I have come from some C# background to Java, and comparing to C#'s LINQ and basic collections with very clean and concise interfaces, Java's collection interfaces sometimes feel like written by a drunk person. Why indeed `Iterator` has `remove` method? C#'s `Enumerator` does not. – Varvara Kalinina Feb 14 '19 at 14:54