1

Guava has collectors like ImmutableSet.toImmutableSet() and ImmutableList.toImmutableList(). Are they thread-safe? Is it safe to use them with parallel streams?

As far as I see the use the regular builders which are not thread-safe:

private static final Collector<Object, ?, ImmutableSet<Object>> TO_IMMUTABLE_SET =
    Collector.of(
        ImmutableSet::<Object>builder,
        ImmutableSet.Builder::add,
        ImmutableSet.Builder::combine,
        ImmutableSet.Builder::build);

On the other hand, the first and third parameters of Collector.of() makes it suspicious that JDK could create a separate builder for every parallel thread and combine their result to make it thread-safe.

palacsint
  • 28,416
  • 10
  • 82
  • 109
  • It seems that they are, since they are `extending` from `ImmutableCollection` which is thread-safe. https://guava.dev/releases/19.0/api/docs/com/google/common/collect/ImmutableCollection.html – Aman Oct 20 '20 at 09:15
  • @Aman No, not really — `ImmutableCollection#Builder` (and its sublasses), which are used in `TO_IMMUTABLE_SET ` `Collector`, don't extend `ImmutableCollection`. See [this question](https://stackoverflow.com/questions/2870744/is-guavas-immutablelist-builder-thread-safe). – Grzegorz Rożniecki Oct 20 '20 at 09:23
  • @Xaerxess thank you, I didn't know that it used a builder. It's clear that builders are non thread safe. – Aman Oct 20 '20 at 09:35
  • 3
    All correctly implemented collectors are thread safe when being used correctly. You don’t need to guess from the parameters, how a collector is supposed to be used. That’s what [the documentation](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collector.html) is for. There’s also [a section in the package documentation](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#MutableReduction). – Holger Oct 20 '20 at 14:46

1 Answers1

3

I believe answer to the question you're supposed to ask is different than to what you actually asked.

No, the collectors are not thread-safe per se (ex. ImmutableList builder performs unsynchronized operations on Object[]), but more importantly collectors don't have to be thread safe to be useful for parallel stream operations. For that see answer from Stuart Marks to question "Parallel streams, collectors and thread safety":

Can non-concurrent collectors be safely used with a parallel stream or should I only use the concurrent versions when collecting from a parallel stream?

It is safe to use a non-concurrent collector in a collect operation of a parallel stream.

For more details, please read the answer and links provided to documentation / contracts of various java.util.stream classes.

Grzegorz Rożniecki
  • 27,415
  • 11
  • 90
  • 112