问题
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!
回答1:
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.
回答2:
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();
}
};
}
回答3:
Collections.unmodifiableList(this.data)
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
回答4:
These views won't return you truly thread-safe collections. There is always the possibility that someone will modify either the backing collection, or the elements within the collection.
To solve this, you need to use immutable collections and immutable elements. Then, thread-safety happens as a result.
Clojure contains such immutable (or persistent) collections.
Put simply, adding or removing new elements returns a new collection, which in general does reuse large parts of the old collection through clever use of Trie-type data structures.
On their own, these are a poor fit for using in straight Java.
Pure4j is an attempt to port these (and the immutable/value based style advocated by Clojure) to the Java language. It might be what you're after.
Disclaimer: I am the developer of Pure4J
来源:https://stackoverflow.com/questions/6658682/how-to-return-a-thread-safe-immutable-collection-in-java