简体   繁体   中英

Preferring mutable or immutable collections as method parameters

I'm writing a library method that will be used in several places. One of the method's parameters is a collection of objects, and the method does not mutate this collection. Should the method signature specify a mutable or immutable collection?

Option 1: mutable collection as parameter

public static void foo(List<Bar> list) {
  // ...
}

Pros: Clients can pass in whichever of List<Bar> or ImmutableList<Bar> is more convenient for them.

Cons: It is not immediately obvious that the list parameter will not be mutated. Clients must read documentation and/or code to realize this. Clients may make unnecessary defensive copies anyway.

Option 2: immutable collection as parameter

public static void foo(ImmutableList<Bar> list) {
  // ...
}

Pros: Clients have a guarantee that the list parameter will not be mutated.

Cons: If the client has a List<Bar> , they must first convert it to an ImmutableList<Bar> before calling foo . This conversion wastes a small amount of time, and it is forced on clients whether they like it or not.


Note: For the purposes of this question, let's assume that all clients will have Guava's ImmutableList available, for example because the library and client code all belong to the same codebase that already uses ImmutableList elsewhere.

As the creator of the foo() API, this is none of your business. You take a list and you don't modify it, and that's it. Your code, in fact, doesn't care about the list's mutability (it's a concern of the caller): so document your intent and stop there.

If the caller needs to guarantee that the list will not be tampered with, they would create defensive copies not because you don't promise to leave the list unchanged, but because they need that guarantee.

It's following the same logic that we perform null checks in method implementations: it's needed because our code needs to be robust, not because the caller can send a null argument.

In other words, document your method as you intend to implement them, and leave it up to the caller to pick the list implementation. The reasons of their choices will vary (ie, it won't always be only whether you'll modify the list).

Leave it at List .

Here are some situations to consider:

  • Collections.synchronizedCollection does not modify the client's collection.
    • If it forced clients to input an immutable collection, there'd be no use in making it a synchronized collection, since an immutable collection would already be thread safe.
  • Collections.frequency does not modify the client's collection.
    • To check frequency, users would be forced to endure the excess overhead of transferring elements to a new collection.

These reasons aren't why the JDK doesn't expose an immutable interface. Those reasons are explained in the documentation . In the case of synchronizedCollection , although it doesn't modify the client's collection, it does return a modifiable view of the client's collection; some would say this function wouldn't apply here. However, frequency and other query functions still hold strong.

You shouldn't restrict clients for the purpose of trying to advertise safety and nothing more. There should be more justification, otherwise your attempt to help could be a burden on the client. In some cases, your goal can be contradictive to what the function/system is achieving, such as with the synchronizedCollection example.

It's good to encourage safety, but having your system force it onto your clients without the system benefiting from it would be abuse of power; that's not your decision to make.


ernest_k makes a really good point in his answer , suggesting that you need to analyze what your system should be in charge of, and what the client should be in charge of. In this case, it should be up to the client whether the collection is immutable or not, since your system doesn't care about mutability. As he put it, " it's none of your business ", which I agree with.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM