Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best practice for returning an internal collection in Java?

I'm curious what is considered a better practice when returning a collection of objects from a mutable class:

public class Someclass {

  public List<String> strings;  

  public add(String in){ strings.add(in); }
  public remove(String in) { strings.remove(in); }   

  //THIS
  public List<String> getStrings(){
    return Collections.unmodifiableList(strings);
  }

  //OR THIS
  public List<String> getStrings(){
    return new ArrayList(strings);
  }
}

I always assumed wrapping the internal collection in an Unmodifiable was the best approach since I didn't see a reason to incur the overhead of creating a copy. However, it occurred to me that any changes made to the list internally would be exposed to the client which strikes me as bad.

like image 744
Eric Rosenberg Avatar asked May 13 '11 00:05

Eric Rosenberg


2 Answers

I don't think there is a simple "best practice" answer to this. It really depends on how much of the machine's resources you are willing to spend on preventing violation of the classes data abstraction boundaries. And it depends on what risks you are actually trying to mitigate; e.g. is it simple (non-concurrent) bugs, concurrency bugs, or information leaks.

The options are:

  • Do nothing; i.e. return the collection as-is.
  • Return the collection wrapped in an immutable wrapper class.
  • Return a shallow copy of the collection.
  • Return a deep copy of the collection.

In addition to the direct costs of copying, other performance-related factors are memory usage and garbage generation and the impact on concurrency. For instance, if multiple threads are updating the collection and/or "getting" it, then making a copy of the collection typically involves locking it ... which could potentially make the operation a concurrency bottleneck.

In summary, you need to balance the cost / performance implications against the potential or actual risks and costs of not taking the precautions.

like image 81
Stephen C Avatar answered Sep 22 '22 14:09

Stephen C


I like to do the latter, but using the .clone() method.

like image 22
V a a m Y o b Avatar answered Sep 26 '22 14:09

V a a m Y o b