How to use an iterator to copy a list - java

If I have a list, and I want to have a method that returns the list without exposing the actual list itself, what would be the best way to do that?
public class open {
private List<Open> users;
public open() {
this.users = new ArrayList<Open>();
}
public List<Open> getUsers() {
//return a copy of the list}
So basically I'd need a copy of the list... I'm guessing that using iterators might be the way to go, but is there a more efficient way to do it?

There are a number of options.
You could use the copy constructor:
return new ArrayList<>(users);
This will explicitly copy the List and return the copy. I wouldn't recommend this unless you really need a mutable copy - it's O(n) obviously.
A much more efficient approach is to use the Collections utility class, this provides a way to return an immutable view:
return Collections.unmodifiableList(users);
As this is a view, return method is O(1) rather than O(n) so more efficient. It deals with ensuring that you cannot modify the List, neither via add & remove etc nor via, for example, Iterator.remove.

It's unnecessary to create a copy of the list. You can return an unmodifiable view of the list with Collections.unmodifiableList.
return Collections.unmodifiableList(users);

Related

Should new instance of Java Collection extension (eg. List) implementation be returned as the return value instead of existing one?

I've been taught that if there is some method which return type is java.util.Collection extension implementation (for this example lets assume it's List interface implemented by ArrayList) I should return its new instance. To be precise let me put here an example:
public List<Something> getListOfSomething() {
List<Something> somethingsList = methodCall(); //some method execution which returns list of something
//some code
return new ArrayList<>(somethingList); //returning list implementation
}
If you look at my snippet you'll see constructor call return new ArrayList<>(somethingList).
My questions are:
Is this correct approach?
If yes (or no) - why?
If it depends - depends on what?
I've been looking for an answer through the Stack, but couldn't even find similar question.
It is safe, as it cannot modify the originally returned list.
However that normally is the resposibility of the called method itself.
You would not like having copies of copies, or needlessly copy.
Under some circumstances you could do:
return Collections.unmodifiableList(somethingList);
The returned list is no longer modifiable, but that might not suit the caller.
I would leave the responsibility to the methodCall to not expose internal data.
If it is a private method, and yours is a public one, then it might be your responsibility. Check whether the data stems from a field, as then you risk exposing internal data to the exterior world.
And finally you could return a Stream which is best.
public Stream<Something> getStreamOfSomething() {
List<Something> somethingsList = methodCall();
...
return somethingList.stream();
}
A Stream gives no access to the List object whether it exposes an internal field to the outside world or not. It everytime gives a new stream/iteration through the list, and one could turn it in a list, or whatever.
Also if you need to do something with the elements of the original list, it is likely you would call .stream() on the list anyway. Otherwise:
List<Something> somethingsList = obj.getStreamOfSomething().collect(Collectors.toList());

Creating a copy of a collection

I'm reading J. Bloch's effective Java and now I'm at the section about avoiding returning nulls, but returning empty collections. This's the code example form the section:
// The right way to return a copy of a collection
public List<Cheese> getCheeseList() {
if (cheesesInStock.isEmpty())
return Collections.emptyList(); // Always returns same list
else
return new ArrayList<Cheese>(cheesesInStock);
}
I really cannot understand what's wrong with just returning the cheesesInStock if cheesesInStock.isEmpty(). why is it better to return the predefined Collections.emptyList(). What kind of troubles we may get into, if we return cheesesInStock instead.
If the method returns cheesesInStock - the caller may add some cheese to the list.
It is a bad practice as you may want to control adding procedure.
Because
you will save resources with Collections.emptyList(); that has a singletton pattern.
it's type-safe
list is immutable (cannot be modified)
Also taking a look at the API you can find:
Returns the empty list (immutable). This list is serializable.
This example illustrates the type-safe way to obtain an empty list:
List<String> s = Collections.emptyList();
Implementation note: Implementations of this method need not create a separate List 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.)
The idea here is more about safe object publication or sharing, returning a reference to a mutable list allows the caller to mutate the original list which is usually a bad idea. If the list or the object in general is immutable then you don't need to do that, String for example is immutable and hence sharing it is safe.
String getString(){
return someString; // no need to copy
}
Shared mutable state comes with two main headaches:
Its hard to check program's correctness when things can be mutated from anywhere.
Thread safety becomes harder because it requires synchronisation which is usually hard and expensive.
If you return cheesesInStock directly, you return a reference to the same List that the one you're object is having (and not a copy of it); so any changes made by someone acquiring this list will reflect in the internal representation of the object. Example:
List<Cheese> list = myObject.getCheeseList();
list.add(new Cheese()); // this also affects the list inside myObject
To prevent from this, it is a good practice to return a copy of the list instead with new ArrayList<Cheese>(previousList). Note that instead of returning a new List, you could also return an unmodifiable view of the List, using Collections.unmodifiableList: this has the same goal - prevent a calling code to modify the internal representation of the object.
The advantage of returning Collections.emptyList(); instead of returning new ArrayList<Cheese>(emptyList) is that you avoid the creation of another object. Also, Collections.emptyList(); represents an immutable List.
The cheesesInStock List can be structurally modified later but a Collections.emptyList() returns an empty list which cannot be structrally modified later.Collections.emptyList() returns EmptyList ,some of the functions are :-
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}

List handling inside a class

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.

Getters and setters and container objects (ArrayList, HashMap, etc)

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.

How to create a deep unmodifiable collection?

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.

Categories

Resources