The second is probably confusing, as it implies that a new value is created and returned - and this is not so.
An exception would be if this method were part of a βsmoothβ API, where the method was an instance method and modifying its instance and then returning the instance to allow the method chain: Java class StringBuilder example of this.
In general, I would not use it either.
I would choose the third option: I am writing a method that creates and returns a new list with the corresponding change. This is a bit artificial in the case of your example, since the example really just plays List.add() , but ...
public static <T> List<T> modifyMyList(List<T> list, T val) { List<T> xs = new ArrayList<T>(list); xs.add(val); return xs; }
In addition: I would not want, as Saket suggested, to return an immutable list. His argument for immutability and parallelism is valid. But most of the time, Java programmers expect to modify the collection, except in special circumstances. By providing you with a method of returning an immutable collection, you limit its reuse for such circumstances. (The caller can always make the list immutable if he wants: they know that the return value is a copy and will not be affected by anything else.) In other words: Java is not Clojure. Also, if parallelism is a concern, take a look at Java 8 and threads (the new type is not I / O threads).
Here is another example:
public static <T> List<T> compact(Iterable<T> it) { List<T> xs = new ArrayList<T>(); for(T x : it) if(x!=null) xs.add(x); return xs; }
Note that I have generalized the method and made it more widely applicable for making Iterable instead of a list. In real code, I would have two overloaded versions, one would take Iterable and one a Iterator . (The first will be implemented by calling the second, with an iterative iterator.) In addition, I made it static, because there was no reason why your method would be an instance method (it does not depend on the state from the instance).
Sometimes, if I write library code, and if it is not clear whether it is more useful to use a mutating or non-mutating implementation, I create both. Here's a more complete example:
public static <T> List<T> compact(Iterable<T> it) { return compact(it.iterator()); } public static <T> List<T> compact(Iterator<T> iter) { List<T> xs = new ArrayList<T>(); while(iter.hasNext()) { T x = iter.next(); if(x!=null) xs.add(x); } return xs; } public static <T> void compactIn(Iterable<T> it) {
If it were in a real API, I would check the arguments for null and throw an IllegalArgumentException. (NOT NullPointerException - although this is often used for this purpose. NullPointerException also occurs for other reasons, for example, with an error. IllegalArgumentException is better for invalid parameters.)
(There will also be more Javadoc than valid code!)