8

I am trying to reverse an unmodifiable list. However i have tried to achieve it but Is it possible to update or reverse and unmodifiable list? I know we can do it with Google Immutable List

import java.util.*;

public class ImmutableList 
 {

public static void main(String args[])
{
    String[] mylist = {"Apple","Orange","Mango","Kiwi","Banana"};
    List reverselist = new ArrayList();
    List<String> strList = Arrays.asList(mylist);
    List<String> unmodifiableList = Collections.unmodifiableList(strList);
    for(int i=unmodifiableList.size();i>0;i--)
    {
        reverselist.add(unmodifiableList.get(i-1));

    }
    List<String> reverse = Collections.unmodifiableList(reverselist);
    System.out.println(reverse);
  }

 }

In the above program I am just traversing in unmodifable list from back and putting them in an array after that adding that array to new unmodifiable list. Can we do it in better way in terms of optimisation?

vkrams
  • 7,267
  • 17
  • 79
  • 129
  • Guava's `ImmutableList` `reverse` method just copy the content of the original `ImmutableList` into a mutable one, call `Collections.reverse` and return a new `ImmutableList`. It doesn't modify the original `ImmutableList` (as your seems to though). – Alexis C. May 03 '14 at 10:38
  • Yeah I know Guava's but is it possible to achieve in unmodifiable? Because If I make any operation I am getting unsupported operation exception in unmodifiable list – vkrams May 03 '14 at 10:41
  • The only way is to copy the content of the original immutable list, reverse the list (or don't do anything if you're looping backwards) and then make it immutable, like Guava does. – Alexis C. May 03 '14 at 10:43

3 Answers3

10

Guava's Lists.reverse(List) returns a reversed view of the original list, without doing any copying.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
3

May be not the best solution but better then reverse ourself:

public List<T> reverseUnModList(List<T> unModListOrig) {
    List<T> tmpList = new ArrayList<T>(unModListOrig); 
    Collections.reverse(tmpList);
    return Collections.unmodifiableList(unModListOrig);
    //return tmpList; //if the result not need to be unmodifieable
}
salyh
  • 2,095
  • 1
  • 17
  • 31
  • 1
    I don't think this is a better solution to reverse looping, as you are copying the list once and then reversing the list. This definitely has more accesses than reverse looping and assigning directly. – anirudh May 03 '14 at 10:47
  • Its not about the amount of accesses, its about the overall duration. Copying the list is a pain, thats right. But then Collections.reverse is only about indexmanipulation using set(). Apart from this the original code from Vikram can be optimized using by not calling in every loop .size():final int size= unmodifiableList.size();for(int i=size;i>0;i--) – salyh May 03 '14 at 11:15
  • Sorry for my confusion, but I don't understand. Vikram's method just loops through the list once and adds the values to the destination list, and so all the values of both the lists are touched only once. That is the same as copying, but in your method, you do extra steps after copying, so how can it be done in less duration? – anirudh May 03 '14 at 11:20
  • You can measure it yourself. My proposal is a little bit faster. With a list of 10000000 strings the code from Vikram needs on my machine 245ms, my proposal needs 61ms. But speed is only one side of optimization. Memory consumption is another one but here the Collections.reverse is also slightly better. – salyh May 03 '14 at 13:56
3

When the list is unmodifiable anyhow, you can just create a reversed view on the list.

This is optimal in terms of performance and storage: It requires O(1) time and O(1) additional space to create this list.

import java.util.AbstractList;
import java.util.Arrays;
import java.util.List;

public class ReversedListViewTest
{
    public static void main(String[] args)
    {
        String[] array = {"Apple","Orange","Mango","Kiwi","Banana"};

        List<String> list = Arrays.asList(array);
        System.out.println("List         : "+list);

        List<String> reversedView = reversedView(list);
        System.out.println("Reversed view: "+reversedView);
    }

    private static <T> List<T> reversedView(final List<T> list)
    {
        return new AbstractList<T>()
        {
            @Override
            public T get(int index)
            {
                return list.get(list.size()-1-index);
            }

            @Override
            public int size()
            {
                return list.size();
            }
        };
    }

}
Marco13
  • 53,703
  • 9
  • 80
  • 159