Say you have a domain class that has an ArrayList attribute. What is the best practise when writing getters and setters for this type of instance (to avoid it being modified)?
public List getList() {
return Collections.unmodifiableList(list);
}
Return a List that is unmodifiable using the Collection.unmodifiableList() method:
Collections - Collection.unmodifiableList()
You can use Collections.unmodifiableList(). There are equivalents for the other major collections types.
Probably best practice is to move the code that operates on the list into the domain class. Possibly add a domain class that represents the sequence in a way appropriate to the domain.
If you are desperate to expose the list, then there is a choice:
return Collections.unmodifiableList(new ArrayList<Thing>(things));
// Bit big - shame there isn't a single method and class to do this.
return new ArrayList<Thing>(things);
// Do you really want to see client code modifying the list?
return Collections.unmodifiableList(things);
// Client may expecting a snapshot, modifications to the original will mess up.
Note if the elements of the list are mutable, you might want to do something about those too.
lweller's response is the what I would do in most cases, but it does throw an UnsupportOperationException which you may not want to deal with. In that case you might want to consider declaring a composite class, like UnmodifiableList, which contains a List of your choosing and exposes all the methods you want to support excluding those that would modify the list. This, of couse, would no longer be type compatible with the Collection interface.
Also consider making an immutable snapshot of the list.
public List getList() {
ArrayList copy = new ArrayList(this.list);
return Collections.unmodifiableList(copy);
}
We have a naming convention where
listXXX();
gives you a read-only list.
There might be setters/getters in addition to that with the proper access modifiers.
Use the guava ImmutableList class. Your getter should then follow the form:
public ImmutableList<T> getMyList() {
ImmutableList.copyOf(myList);
}
The advantage of guava over the Collections.unmodifiableList is that it reveals to the client that your colllection is immutable in the method signature, so there's very little chance of people mistakenly trying to add something to the collection.
Related
I need some class/interface name that describes an immutable, ordered set (in input order, like LinkedHashSet). I can of course just use the class like this:
class Foo {
public final Set<Long> frozenOrderedSet;
public Foo(List<Long> input) {
frozenOrderedSet = Collections.unmodifiableSet(new LinkedHashSet(input));
}
}
But this would not clarify my approach. I would like to make it clear to everyone reading the source that the Set is unmodifiable and unique while maintaining it's order with for(Long l : set){}.
Guava's ImmutableSet provides a high-performance, immutable Set with reliable, user-specified iteration order. There are also variations like ImmutableSortedSet.
The simplest way would be extend Set to create a custom immutable Set.
public CustomImmutableSet(){ return Collections.unmodifiableSet(new
LinkedHashSet(input)); }
This way it will make it clear to everyone reading the source that the Set is unmodifiable and unique
Bozho in question Java Immutable Collections:
Unmodifiable collections are usually read-only views (wrappers) of
other collections. You can't add, remove or clear them, but the
underlying collection can change.
Immutable collections can't be changed at all - they don't wrap
another collection - they have their own elements.
Here's a quote from guava's ImmutableList
Unlike Collections.unmodifiableList(java.util.List),
which is a view of a separate collection that can still change, an
instance of ImmutableList contains its own private data and will never
change.
So, basically, in order to get an immutable collection out of a
mutable one, you have to copy its elements to the new collection, and
disallow all operations.
So Basically you might create subclass of class TreeSet and override all :add, remove etc. methods to just throw an Exception saying that this is immutable collection. Also you would have to create copying constructor in this class with one parameter TreeSet setToCopyFrom.
I was looking around for some elegant solution to removing null values from a List. I came across the following post, which says I can use list.removeAll(Collections.singletonList(null));
This, however, throws an UnsupportedOperationException, which I'm assuming is because removeAll() is attempting to do some mutative operation on the immutable singleton collection. Is this correct?
If this is the case, what would be a typical use of this singletonList? To represent a collection of size 1 when you're sure you don't want to actually do anything with the collection?
Thanks in advance.
It works like a charm:
List<String> list = new ArrayList<String>();
list.add("abc");
list.add(null);
list.add("def");
list.removeAll(Collections.singletonList(null));
System.out.println(list); //[abc, def]
Indeed Collections.singletonList(null) is immutable (which is unfortunately hidden in Java[1]), but the exception is thrown from your list variable. Apparently it is immutable as well, like in example below:
List<String> list = Arrays.asList("abc", null, "def");
list.removeAll(Collections.singletonList(null));
This code will throw an UnsupportedOperationException. So as you can see singletonList() is useful in this case. Use it when client code expects a read-only list (it won't modify it) but you only want to pass one element in it. singletonList() is (thread-)safe (due to immutability), fast and compact.
[1] E.g. in scala there is a separete hierarchy for mutable and immutable collections and API can choose whether it accept this or the other (or both, as they have common base interfaces)
To answer your actual question :
what would be a typical use of this singletonList? To represent a collection of size 1 when you're sure you don't want to actually do anything with the collection?
The typical use is if you have one element and want to pass it to a method that accepts a List, ie
public void registerUsers(List<User> users) {...}
User currentUser = Login Manager.getCurrentUser();
registerUsers(Collections.singletonList(currentUser));
The removeAll() is a special case for this.
Has your list been protected with
Collections.unmodifiableList(list)
Because if you have protected it and try to modify it later you get that error.
Let's say I have a class A that has a list of related elements (type of elements not relevant):
public class A {
private List<String> list;
public List<String> getList() {
return list;
}
public void addElement(String element) {
list.add(element);
}
}
Now I want access to this list from another class, Client. I need to add a new element. The question, a more phylosophical one, is how best is this done from a design point of view.
public class Client {
private A a = new A();
public void method1() {
a.getList().add("");
}
public void method2() {
a.addElement("");
}
}
If anyone could point out any advantage of any of these methods, would be much appreciated.
Thanks.
Generally your getList() method is considered bad style. If class A returns a reference to its actual List, than a caller might call clear() on that list, or add a million elements to it, or so who-knows-what-all. It's a much better idea to return only an Iterator, or only a read-only view of the List using Collections.unmodifiableList().
This means your solution 2, addElement() is better; the addElement() method might contain code to validate the added elements, limit the size of the list, or whatever. And clear() would not be accessible.
If your intention is to really expose the list, method2 is usually a better OOP-style. (Since by using method2 you'll get addAll etc for free.)
Examples of this pattern in the standard API:
HashMap.keySet
Subject.getPrincipals
The documentation should take care to say something like The object is backed by the returned collection, so modifications will ...
The drawback is that by exposing the list you allow clients to do remove and so on, so if your intention is to just collect items through add then method1 may still be a better choice.
Examples of this pattern in the standard API:
Component.addKeyListener
DefaultTableModel.addRow
I wouldn't give access to the list (i.e. getList()) its good however that you added a addElement method. That is a good idea because you can put restrictions on what can be added to the list in that method.
I would choose
public void method2() {
a.addElement("");
}
Because mantains hidden the list inside A. Of course this depends on how related is the list to A if only instances of A should get a reference to the list then this is my choice.
One other reason might be that giving away the list could lead to clients removing items, you might want to avoid clients to consider the list as their own, it's A's, keep it safe! :P
Otherwise the list does not belong to A and should be removed from it.
You should most definitely hide the underlying list in class A. A should not provide a getList() method if possible.
Class B should use a.addElement() exclusively. And, if B needs to read from the list in A, A should provide methods for accessing the list instead of giving B the entire list.
One of the main tenants of OO programming is Encapsulation. Which means that you should hide the underlying implementation of your classes, and abstract out that low-level info.
To your specific question, you will want to use method2(). You shouldn't even be able to use a.getList() from class B if you are following proper OO principles.
When coding, you should consider the maintenance process. The less the classes know about each other the better it it is.
The client should only know that A can have elements .... so I will consider the second design as being much better.
You should provide a method for adding element on class A. Returning the original List is wrong from the design point of view because the user of your class has full access to it.
method2 is better because the client doesnt need to bother with the list implementation. if class A changes its data structure, the client is not affected.
I usually always find it sufficient to use the concrete classes for the interfaces listed in the title. Usually when I use other types (such as LinkedList or TreeSet), the reason is for functionality and not performance - for example, a LinkedList for a queue.
I do sometimes construct ArrayList with an initial capcacity more than the default of 10 and a HashMap with more than the default buckets of 16, but I usually (especially for business CRUD) never see myself thinking "hmmm...should I use a LinkedList instead ArrayList if I am just going to insert and iterate through the whole List?"
I am just wondering what everyone else here uses (and why) and what type of applications they develop.
Those are definitely my default, although often a LinkedList would in fact be the better choice for lists, as the vast majority of lists seem to just iterate in order, or get converted to an array via Arrays.asList anyway.
But in terms of keeping consistent maintainable code, it makes sense to standardize on those and use alternatives for a reason, that way when someone reads the code and sees an alternative, they immediately start thinking that the code is doing something special.
I always type the parameters and variables as Collection, Map and List unless I have a special reason to refer to the sub type, that way switching is one line of code when you need it.
I could see explicitly requiring an ArrayList sometimes if you need the random access, but in practice that really doesn't happen.
For some kind of lists (e.g. listeners) it makes sense to use a CopyOnWriteArrayList instead of a normal ArrayList. For almost everything else the basic implementations you mentioned are sufficient.
Yep, I use those as defaults. I generally have a rule that on public class methods, I always return the interface type (ie. Map, Set, List, etc.), since other classes (usually) don't need to know what the specific concrete class is. Inside class methods, I'll use the concrete type only if I need access to any extra methods it may have (or if it makes understanding the code easier), otherwise the interface is used.
It's good to be pretty flexible with any rules you do use, though, as a dependancy on concrete class visibility is something that can change over time (especially as your code gets more complex).
Indeed, always use base interfaces Collection, List, Map instead their implementations. To make thinkgs even more flexible you could hide your implementations behind static factory methods, which allow you to switch to a different implementation in case you find something better(I doubt there will be big changes in this field, but you never know). Another benefit is that the syntax is shorter thanks to generics.
Map<String, LongObjectClasName> map = CollectionUtils.newMap();
instead of
Map<String, LongObjectClasName> map = new HashMap<String, LongObjectClasName>();
public class CollectionUtils {
.....
public <T> List<T> newList() {
return new ArrayList<T>();
}
public <T> List<T> newList(int initialCapacity) {
return new ArrayList<T>(initialCapacity);
}
public <T> List<T> newSynchronizedList() {
return new Vector<T>();
}
public <T> List<T> newConcurrentList() {
return new CopyOnWriteArrayList<T>();
}
public <T> List<T> newSynchronizedList(int initialCapacity) {
return new Vector<T>(initialCapacity);
}
...
}
Having just come out of a class about data structure performance, I'll usually look at the kind of algorithm I'm developing or the purpose of the structure before I choose an implementation.
For example, if I'm building a list that has a lot of random accesses into it, I'll use an ArrayList because its random access performance is good, but if I'm inserting things into the list a lot, I might choose a LinkedList instead. (I know modern implementations remove a lot of performance barriers, but this was the first example that came to mind.)
You might want to look at some of the Wikipedia pages for data structures (especially those dealing with sorting algorithms, where performance is especially important) for more information about performance, and the article about Big O notation for a general discussion of measuring the performance of various functions on data structures.
I don't really have a "default", though I suppose I use the implementations listed in the question more often than not. I think about what would be appropriate for whatever particular problem I'm working on, and use it. I don't just blindly default to using ArrayList, I put in 30 seconds of thought along the lines of "well, I'm going to be doing a lot of iterating and removing elements in the middle of this list so I should use a LinkedList".
And I almost always use the interface type for my reference, rather than the implementation. Remember that List is not the only interface that LinkedList implements. I see this a lot:
LinkedList<Item> queue = new LinkedList<Item>();
when what the programmer meant was:
Queue<Item> queue = new LinkedList<Item>();
I also use the Iterable interface a fair amount.
If you are using LinkedList for a queue, you might consider using the Deque interface and ArrayDeque implementing class (introduced in Java 6) instead. To quote the Javadoc for ArrayDeque:
This class is likely to be faster than
Stack when used as a stack, and faster
than LinkedList when used as a queue.
I tend to use one of *Queue classes for queues. However LinkedList is a good choice if you don't need thread safety.
Using the interface type (List, Map) instead of the implementation type (ArrayList, HashMap) is irrelevant within methods - it's mainly important in public APIs, i.e. method signatures (and "public" doesn't necessarily mean "intended to be published outside your team).
When a method takes an ArrayList as a parameter, and you have something else, you're screwed and have to copy your data pointlessly. If the parameter type is List, callers are much more flexible and can, e.g. use Collections.EMPTY_LIST or Collections.singletonList().
I too typically use ArrayList, but I will use TreeSet or HashSet depending on the circumstances. When writing tests, however, Arrays.asList and Collections.singletonList are also frequently used. I've mostly been writing thread-local code, but I could also see using the various concurrent classes as well.
Also, there were times I used ArrayList when what I really wanted was a LinkedHashSet (before it was available).
I often make a collection field unmodifiable before returning it from a getter method:
private List<X> _xs;
....
List<X> getXs(){
return Collections.unmodifiableList(_xs);
}
But I can't think of a convenient way of doing that if the X above is itself a List:
private List<List<Y>> _yLists;
.....
List<List<Y>> getYLists() {
return Collections.unmodifiableList(_yLists);
}
The problem in the above is of course that though the client cannot modify the List of lists, it can add/delete Y objects from the embedded lists.
Any thoughts?
The best I could come up with uses ForwardingList from Google Collections. Comments are welcome.
private static <T> List<List<T>> unmodifiableList2(final List<List<T>> input) {
return Collections.unmodifiableList(new ForwardingList<List<T>>() {
#Override protected List<List<T>> delegate() {
return Collections.unmodifiableList(input);
}
#Override public List<T> get(int index) {
return Collections.unmodifiableList(delegate().get(index));
}
});
}
unfortunately, there is no easy way to get deep const-ness in java. you would have to hack around it by always making sure that the list inside the list is also unmodifiable.
i'd be interested too to know any elegant solution.
The clojure collections (map, set, list, vector) can all be nested and are immutable by default. For pure java, there is this library:
http://code.google.com/p/pcollections/
If you look at the implementation of the Collections.unmodifiable*(...) methods, you can see that they just wrap the collection. Doing a deep utility in same way should be doable.
The downside of this is that it adds extra method call to the collection access and so affects performance.
If your only goal here is to enforce encapsulation, a classic solution is to use clone() or similar to return a structure that is not the internal state of the object. This obviously only works if all the objects can be cloned, and if the copied structure is small enough.
If this is a fairly commonly used data structure, another option is to make the API that accesses it more concrete, so that you have more detailed control over the specific calls. Writing your own List implementation, as above is one way to do this, but if you can narrow down the calls to specific use cases, you can expose specific access APIs instead of the List interface.
Just in case someone is interested here is a simple solution:
public List<List<Double>> toUnmodifiable(List<List<Double>> nestedList) {
List<List<Double>> listWithUnmodifiableLists = new ArrayList<>();
for (List<Double> list : nestedList) {
listWithUnmodifiableLists
.add(Collections.unmodifiableList(list));
}
return Collections.unmodifiableList(listWithUnmodifiableLists);
}
This can be used for example as a solution if u want to expose a list with a getList() method, you can return: toUnmodifiable(mNestedList), where mNestedList is the private list in the class.
I personally found this useful when implementing a class used for parsing with GSON in Android, since it doesn't make sense to be able to modify a response, in this case the de-serialized json, I used this method as a way to expose the list with a getter and made sure the list wont be modified.