This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Collections.emptyList() vs. new instance
I was trying to understand the difference between create a new instance of a list using:
new ArrayList<X>
and
Collections.emptyList();
As I understood, the later returns an immutable list. That means that it is not possible to add,delete, or modify it.
I want to know why one would create and immutable emptyList ? what is the use?
thanks
Being immutable allows for reusable instances.
Collections.emptyList will always return the exact same singleton instance.
This is very efficient.
In addition to that, immutable data can be safely shared between threads, and is guaranteed to avoid weird side-effects due to coding errors. For that reason it makes defensive copies unnecessary, too.
Say you have to return a collection and you don't want to creating a couple of objects each time.
interface Configurable {
List<String> getConfigurationList();
}
// class which doesn't have any configuration
class SimpleConfigurable implements Configurable {
public List<String> getConfigurationList() { return Collections.emptyList(); }
}
Returning an empty collection is often preferable to returning null
I often use empty lists as Null objects: this avoid having to check for null.
I've used Collections.emptyList for methods that return a list but that are called with arguments that don't make sense.
For instance a stream processing application where you want to access different parts of the stream, perhaps based on dates. You query for a time span of items from the stream but if there are no items in that time span you would return an empty list. Throwing an exception wouldn't make any sense since the isn't anything wrong with the query. Returning null also doesn't make much sense because then all the calling code needs to check for null.
Returning an immutable empty list allows the calling code the handle the return value nicely, you don't need to worry about threading issues since an immutable list is inherently thread safe.
To avoid Unwanted NullPointerException.
In your code, you may return a normal "empty" ArrayList instead of returning null. But, in that way, you will keep creating NEW objects (with default capacity of 10) on each execution which is not a memory efficient approach. Instead of that if you return emptyList, the same instance will be returned on every invocation. This way it saves you from unwanted NullPointerException in a more efficient way. Here is the snip from the Javadoc for emptyList:
/**
* Returns the empty list (immutable). This list is serializable.
*
* <p>This example illustrates the type-safe way to obtain an empty list:
* <pre>
* List<String> s = Collections.emptyList();
* </pre>
* Implementation note: Implementations of this method need not
* create a separate <tt>List</tt> object for each call. Using this
* method is likely to have comparable cost to using the like-named
* field. (Unlike this method, the field does not provide type safety.)
*
* #see #EMPTY_LIST
* #since 1.5
*/
Related
This question already has answers here:
Collections.emptyList() vs. new instance
(7 answers)
Closed 3 years ago.
I found emptyEnumeration(), emptyIterator(), emptyList() and other methods in Collections class. I searched for examples and purpose but could not found an appropriate one.
It would be a great help if someone can explain with project usability example, wehre emptyList() needs to be created and it is also better to go with it than going with creating a new ArrayList<>() without adding any elements.
They actually return a casted, single instance, so you don't create new objects on the heap for each call to emptyList(). So it's faster and saves memory and GC.
It's an initializer that is used internally by List implementations to decide whether they actually need to allocate space (even adding elements) or keep the list untouched if no elements will be added at runtime (because it happens sometimes, more often than you may think).
Those objects are immutable so you can safely reuse the same instance anywhere, without the synchronization you usually put in place to ensure object status integrity.
The purpose of the empty collection is to be an empty collection! As remarked in a comment, there are times when it is appropriate for a method that returns a collection to be returning an empty collection.
As for why (e.g.) Collections.emptyList() is useful: well, why create your own empty list when you can reuse an existing empty list? It's a minor convenience, a minor saving on memory.
If your code naturally arrives at a point where it (a) knows it needs to return an empty collection, and (b) does not have an empty collection that was created 'naturally', by which I mean something like having created the collection to hold results and then failed to find any such results, then the Collections facilities are handy.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
The continuation of the question.
I need to statically and publicly storage data as arrays but I don't want somebody to modify my data. I need only ability to read from those arrays. Therefore I think I should use something like constant arrays which are presented in C++.
As far as I understand Collections.unmodifiableList(Arrays.asList(...)) prevents from modify the list at run-time but not at compile-time.
I've made the following class (code is updated). I suppose I'm not reinventing the wheel because I cannot have the same result using unmodifiableList.
/**
* Emulates constant arrays from C++.
*
* #param <E> Type of elements. Has to be immutable type.
*/
public final class ConstArray<E> {
/** Stores elements. */
private final E[] storage;
/**
* Constructs the object.
*
* #param storage Elements.
*/
public ConstArray(final E[] storage) {
this.storage = storage.clone();
}
/**
* Returns element at {#code idx}.
*
* #param idx Index of returning element.
* #return Element at {#code idx}.
*/
public final E get(final int idx) {
return storage[idx];
}
}
The size method and some other methods are omitted.
I've tested the class and it works.
To paraphrase, if I provide my library and somebody try to modify my data, I think it's better when he/she will know immediately that it's not possible (my class doesn't have a method to modify anything) and if I used unmodifiableList he/she will notice only a crash of the program.
What are advantages and disadvantages of this class? Is there a way to improve this class?
UPD:
I decided to use #Hoopje 's advice (see answers). It's based on experience that I don't have: I'm only a Java beginner.
If "reinventing the wheel" is not disadvantage enough, I see one major disadvantage to your approach:
Arrays.asList and Collections.ummodifiableList return List instances, so they are integrated in the Java Collections framework. This means that you can easily use them in enhanced for loops (for (E item : list) { }), as streams (list.stream()), use all List methods, pass them to methods which expect Collection or List subclasses, etc.
A minor point is that your class makes a copy of the array, whereas both Arrays.asList and Collections.ummodifiableList return views of their argument, so they do not copy the array.
By the way, creating a shallow copy of an array does not require "magic": you can do
this.storage = storage.clone();
Answer to UPD1:
Yes, it is unfortunate that Java does not provide interfaces for collections which cannot be modified. Thus, immutable List instances will have, for example, an add(E) method which simply throws an exception. So there is no compile-time guarantee for immutability.
However, in the Javadoc for your method you will of course write that the returned list is immutable. And if the user of your library tests his/her software, he will very deterministically see the exception and realize that he/she made a programming error.
And believe me, the users of your library will very much hate you if you take away their possibility to use the returned list in Collection-based APIs, just for the small advantage of not having any methods that look as if they would modify it.
I don't understand this method implementation. It's
public static <T> List<T> add(List<T> list, T element) {
final int size = list.size();
if (size == 0) {
return ImmutableList.of(element);
} else if (list instanceof ImmutableList) {
if (size == 1) {
final T val = list.get(0);
list = Lists.newArrayList();
list.add(val);
} else {
list = Lists.newArrayList(list);
}
}
list.add(element);
return list;
}
Why not a straightforward list.add(element)?
The code is implementing adding to the list that's given. If the input list is an ImmutableList, it first creates a mutable list (since otherwise it can't add to it) and copies the elements to it. If it's not, it just uses the existing list.
It's a bit odd that it returns an ImmutableList if the list passed in is empty, but a (mutable) ArrayList if it's given a non-empty ImmutableList to add to, but perhaps that makes sense in the broader context of where and how it's used. But that inconsistency is definitely something I'd query in a code review.
Addition for ImmutableList
Why not a strightforward list.add(element)?
You can't call that method if the given list is immutable. Actually you can but usually such a method will then throw an UnsupportedOperationException. The documentation of Guavas ImmutableList#add says
Deprecated. Unsupported operation.
Guaranteed to throw an exception and leave the list unmodified.
However the goal of the method seems to be to also support addition for ImmutableList by creating a mutable clone. So a straightforward implementation would be:
public static <T> List<T> add(List<T> list, T element) {
if (list instanceof ImmutableList) {
// Create mutable clone, ArrayList is mutable
list = Lists.newArrayList(list);
}
list.add(element);
return list;
}
Other stuff
Note that the type may change. While the input may be an ImmutableList, the output definitely is not.
You could keep the type by creating a temporary clone, adding to it (as shown) and then again wrap some ImmutableList around. However that doesn't seem to be a goal of this method.
Also note that the method in same cases may add something to the given list and in some create a new instance instead. So the caller of the method must be aware of the method sometimes changing his argument and sometimes not. For me this is a very odd behavior, it definitely must be highlighted in the documentation but I would not recommend doing stuff like that.
It seems that another goal of the method is to keep the list immutable if it was empty at method call. This is a bit strange but probably highlighted in its documentation. Therefore they add this call:
if (size == 0) {
return ImmutableList.of(element);
}
Besides that they do some minor stuff by calling
Lists.newArrayList();
instead of
Lists.newArrayList(list);
if the list is currently of size 1. However I'm not sure why they do this step. In my opinion they could just leave it the way it was.
So all in all I would probably implement such a method as
/**
* Creates a new list with the contents of the given list
* and the given element added to the end.
*
* <T> The type of the lists elements
*
* #params list The list to use elements of, the list will not be changed
* #params element The element to add to the end of the resulting list
*
* #return A new list with the contents of the given list and
* the given element added to the end. If the given list was
* of type {#link ImmutableList} the resulting list will
* also be of type {#link ImmutableList}.
**/
public static <T> List<T> add(List<T> list, T element) {
List<T> result;
// Create a Stream of all elements for the result
Stream<T> elements = Stream.concat(list.stream(), Stream.of(element));
// If the list was immutable, make the result also immutable
if (list instanceof ImmutableList) {
result = ImmutableList.of(elements.toArray(T[]::new));
} else {
result = elements.collect(Collectors.toList());
}
return result;
}
By that you won't ever change the argument list and you will also keep the list ImmutableList if it was. Using the Stream#concat method makes things a bit more efficient here (it is a lazy method), otherwise we would need to create temporary clones in between.
However we do not know which goals your method has, so probably in the context of your specific method what it does it makes more sense.
This method is an anti-pattern, and should not be used. It munges mutable and immutable data structures, providing the worst of both implementations.
If you're using an immutable data structure you should make that clear in your types - casting to List loses that important context. See the "Interfaces" not implementations section of ImmutableCollection.
If you're using a mutable data you should avoid doing linear-time copies and instead take advantage of the data structure's mutability (carefully).
It generally does not make sense to use the two types interchangeably - if you want to add things to an existing collection use a mutable collection you own. If you intend for the collection to be immutable, don't try to add things to it. This method discards that intent and will lead to runtime errors and/or reduced performance.
The reason that this method is not "a straightforward list.add(element)" is because this method is designed to be able to add elements to ImmutableLists. Those are, quite obviously, immutable (if you look, their native add method throws an UnsupportedOperationException) and so the only way to "add" to them is to create a new list.
The fact that the newly returned list is now mutable is a strange design decision and only a wider context or input from the code's author would help solve that one.
The special case where an empty input list will return an immutable list is another strange design decision. The function would work fine without that conditional branch.
Because this method returns a copy of the list, you should be careful to assign the result to something, probably the original variable:
myList = TheClass.add(myList, newElement);
and note that the following usage will effectively do nothing:
TheClass.add(myList, newElement);
I have a class with a private mutable list of data.
I need to expose list items given following conditions:
List should not be modifiable outside;
It should be clear for developers who use getter function that a list they get can not be modified.
Which getter function should be marked as recommended approach? Or can you offer a better solution?
class DataProcessor {
private final ArrayList<String> simpleData = new ArrayList<>();
private final CopyOnWriteArrayList<String> copyData = new CopyOnWriteArrayList<>();
public void modifyData() {
...
}
public Iterable<String> getUnmodifiableIterable() {
return Collections.unmodifiableCollection(simpleData);
}
public Iterator<String> getUnmodifiableIterator() {
return Collections.unmodifiableCollection(simpleData).iterator();
}
public Iterable<String> getCopyIterable() {
return copyData;
}
public Iterator<String> getCopyIterator() {
return copyData.iterator();
}
}
UPD: this question is from a real code-review discussion on the best practice for list getter implementation
The "best" solution actually depends on the intended application patterns (and not so much on "opinions", as suggested by a close-voter). Each possible solution has pros and cons that can be judged objectively (and have to be judged by the developer).
Edit: There already was a question "Should I return a Collection or a Stream?", with an elaborate answers by Brian Goetz. You should consult this answers as well before making any decision. My answer does not refer to streams, but only to different ways of exposing the data as a collection, pointing out the pros, cons and implications of the different approaches.
Returning an iterator
Returning only an Iterator is inconvenient, regardless of further details, e.g. whether it will allow modifications or not. An Iterator alone can not be used in the foreach loop. So clients would have to write
Iterator<String> it = data.getUnmodifiableIterator();
while (it.hasNext()) {
String s = it.next();
process(s);
}
whereas basically all other solutions would allow them to just write
for (String s : data.getUnmodifiableIterable()) {
process(s);
}
Exposing a Collections.unmodifiable... view on the internal data:
You could expose the internal data structure, wrapped into the corresponding Collections.unmodifiable... collection. Any attempt to modify the returned collection will cause an UnsupportedOperationException to be thrown, clearly stating that the client should not modify the data.
One degree of freedom in the design space here is whether or not you hide additional information: When you have a List, you could offer a method
private List<String> internalData;
List<String> getData() {
return Collections.unmodifiableList(internalData);
}
Alternatively, you could be less specific about the type of the internal data:
If the caller should not be able to do indexed access with the List#get(int index) method, then you could change the return type of this method to Collection<String>.
If the caller additionally should not be able to obtain the size of the returned sequence by calling Collection'size(), then you could return an Iterable<String>.
Also consider that, when exposing the less specific interfaces, you later have the choice to change the type of the internal data to be a Set<String>, for example. If you had guaranteed to return a List<String>, then changing this later may cause some headaches.
Exposing a copy of the internal data:
A very simple solution is to just return a copy of the list:
private List<String> internalData;
List<String> getData() {
return new ArrayList<String>(internalData);
}
This may have the drawback of (potentially large and frequent) memory copies, and thus should only be considered when the collection is "small".
Additionally, the caller will be able to modify the list, and he might expect the changes to be reflected in the internal state (which is not the case). This problem could be alleviated by additionally wrapping the new list into a Collections.unmodifiableList.
Exposing a CopyOnWriteArrayList
Exposing a CopyOnWriteArrayList via its Iterator or as an Iterable is probably not a good idea: The caller has the option to modify it via Iterator#remove calls, and you explicitly wanted to avoid this.
The solution of exposing a CopyOnWriteArrayList which is wrapped into a Collections.unmodifiableList may be an option. It may look like a superfluously thick firewall at the first glance, but it definitely could be justified - see the next paragraph.
General considerations
In any case, you should document the behavior religiously. Particularly, you should document that the caller is not supposed to change the returned data in any way (regardless of whether it is possible without causing an exception).
Beyond that, there is an uncomfortable trade-off: You can either be precise in the documentation, or avoid exposing implementation details in the documentation.
Consider the following case:
/**
* Returns the data. The returned list is unmodifiable.
*/
List<String> getData() {
return Collections.unmodifiableList(internalData);
}
The documentation here should in fact also state that...
/* ...
* The returned list is a VIEW on the internal data.
* Changes in the internal data will be visible in
* the returned list.
*/
This may be an important information, considering thread safety and the behavior during iteration. Consider a loop that iterates over the unmodifiable view on the internal data. And consider that in this loop, someone calls a function that causes a modification of the internal data:
for (String s : data.getData()) {
...
data.changeInternalData();
}
This loop will break with a ConcurrentModificationException, because the internal data is modified while it is being iterated over.
The trade-off regarding the documentation here refers to the fact that, once a certain behavior is specified, clients will rely on this behavior. Imagine the client does this:
List<String> list = data.getList();
int oldSize = list.size();
data.insertElementToInternalData();
// Here, the client relies on the fact that he received
// a VIEW on the internal data:
int newSize = list.size();
assertTrue(newSize == oldSize+1);
Things like the ConcurrentModificationException could have been avoided if a true copy of the internal data had been returned, or by using a CopyOnWriteArrayList (each wrapped into a Collections.unmodifiableList). This would be the "safest" solution, in this regard:
The caller can not modify the returned list
The caller can not modify the internal state directly
If the caller modifies the internal state indirectly, then the iteration still works
But one has to think about whether so much "safety" is really required for the respective application case, and how this can be documented in a way that still allows changes to the internal implementation details.
Typically, Iterator is used only with Iterable, for the purpose of for-each loop. It'll be pretty odd to see a non-Iterable type contains a method returning Iterator, and it maybe upsetting to the user that it cannot be used in for-each loop.
So I suggest Iterable in this case. You could even have your class implements Iterable if that makes sense.
If you want to jump on the Java 8 wagon, returning a Stream probably is a more "modern" approach.
By encapsulation rules you had to always return an unmodifiable list, in your case is a design rule, so return the Collections.unmodifiableCollection, and you don't need to name the method as getUnmodifiable, use getter naming convenction and use Javadoc to tell other developer what kind of list you return and why...careless users will be alerted with an exception!!
I encounter many times of similar code:
class AClass{
private Iterable<String> list;
public AClass(Iterable<String> list){ this.list = list; }
...
}
In this code, a reference of Iterable is passed to AClass directly. The end result is equivalent to directly expose list reference to outside. Even if you make AClass.list final, it still allows code from outside AClass to modify the content of the list, which is bad.
To counter this, we will do a defensive copy in the constructor.
However, this kind of code is very common. Besides performance consideration, what's the intension for people to write this kind of code?
I don't see anything wrong with that pattern. If the class represents objects that operate on a list (or an iterable) then it's natural to provide that list to the constructor. If your class can't handle changes to the underlying collection, then it needs to be fixed or documented. Making a copy of the collection is one way to fix that.
Another option is to change the interface so that only immutable collections are allowed:
public AClass(ImmutableList<MyObject> objects) {
this.objects = objects;
...
You would need some kind of ImmutableList-class or interface of course.
Depending on the use and users of your classes you could also avoid making copies by documenting the known "weakness":
/**
* ...
* #param objects list of objects this AClass-object operates on.
* The list should not be modified during the lifetime
* of this object
*/
public AClass(List<MyObject> objects) ...
Simple answer, if it is your own code/small team, it is often just quicker, easier and less memory and CPU intensive to do things this way. Also, some people just don't know any better!
You might want to take a look at the copy constructor for a familiar idiom.
Its always good practice to make a copy, not only because other people can then modify your values, but also for security reasons.
If the code is being used internally as is pointed by other answers it should not be a problem. But if you are exposing as an API then there are two options:
First is to create a defensive copy and then return it
Second would be to create a UnmodifiableCollection and then return it and document the fact that trying to change anything in the collection may result in exception.
But the first option is more preferable.