Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return a thread safe/immutable Collection in Java?

In the project I am coding, I need to return a thread safe and immutable view from a function. However, I am unsure of this. Since synchronizedList and unmodifiableList just return views of a list, I don't know if

Collections.synchronizedList(Collections.unmodifiableList(this.data));

would do the trick.

Could anyone tell me if this is correct, and in case it is not, are there any situations that this would likely to fail?

Thanks for any inputs!

like image 923
zw324 Avatar asked Jul 12 '11 01:07

zw324


3 Answers

I find this to be a real gap in the JDK. Fortunately, a team over a Google, led by Java Collections designer Joshua Bloch, have created a library that includes truly immutable collections.

ImmutableList in particular is the implementation you're looking for. Here is a quick sketch of some of the features of Guava's ImmutableCollections.

like image 179
Ray Avatar answered Oct 21 '22 06:10

Ray


I think unmodifiable is sufficient. You can't write to it, which is what causes problems for multi-threaded access. It's read-only, so the additional step of synchronizing seems unnecessary to me.

Best to check out the source code when there are questions like this. Looks like it returns an UnmodifiableList:

/**
 * @serial include
 */
static class UnmodifiableList<E> extends UnmodifiableCollection<E>
                  implements List<E> {
    static final long serialVersionUID = -283967356065247728L;
final List<? extends E> list;

UnmodifiableList(List<? extends E> list) {
    super(list);
    this.list = list;
}

public boolean equals(Object o) {return o == this || list.equals(o);}
public int hashCode()       {return list.hashCode();}

public E get(int index) {return list.get(index);}
public E set(int index, E element) {
    throw new UnsupportedOperationException();
    }
public void add(int index, E element) {
    throw new UnsupportedOperationException();
    }
public E remove(int index) {
    throw new UnsupportedOperationException();
    }
public int indexOf(Object o)            {return list.indexOf(o);}
public int lastIndexOf(Object o)        {return list.lastIndexOf(o);}
public boolean addAll(int index, Collection<? extends E> c) {
    throw new UnsupportedOperationException();
    }
public ListIterator<E> listIterator()   {return listIterator(0);}

public ListIterator<E> listIterator(final int index) {
    return new ListIterator<E>() {
    ListIterator<? extends E> i = list.listIterator(index);

    public boolean hasNext()     {return i.hasNext();}
    public E next()          {return i.next();}
    public boolean hasPrevious() {return i.hasPrevious();}
    public E previous()      {return i.previous();}
    public int nextIndex()       {return i.nextIndex();}
    public int previousIndex()   {return i.previousIndex();}

    public void remove() {
        throw new UnsupportedOperationException();
            }
    public void set(E e) {
        throw new UnsupportedOperationException();
            }
    public void add(E e) {
        throw new UnsupportedOperationException();
            }
    };
}
like image 43
duffymo Avatar answered Oct 21 '22 05:10

duffymo


Collections.unmodifiableList(this.data) 

Statement above will do, as it will return a view. Any modification attempts on this view will result of UnsupportedOperationException being thrown. Below are excerpt of Collections#unmodifiableList documentation.

Returns an unmodifiable view of the specified list. This method allows modules to provide users with "read-only" access to internal lists. Query operations on the returned list "read through" to the specified list, and attempts to modify the returned list, whether direct or via its iterator, result in an UnsupportedOperationException.

......

java 8 java.util.Collections javadoc

like image 24
Awan Biru Avatar answered Oct 21 '22 06:10

Awan Biru