Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ImmutableCollection.Builder Java8-Collector-friendly #1582

Closed
gissuebot opened this issue Oct 31, 2014 · 13 comments
Closed

Make ImmutableCollection.Builder Java8-Collector-friendly #1582

gissuebot opened this issue Oct 31, 2014 · 13 comments

Comments

@gissuebot
Copy link

Original issue created by Eric6iese on 2013-11-17 at 06:05 AM


The upcoming JDK-8 contains the new Stream-API, which is somewhat comparable to FluentIterable - expect that its core abstraction is the iterator, and not the Iterable. But its pattern to create new Collections after a stream chain is different than guava's:

list.stream().collect(Collectors.toList());

The collect-Method takes a Collector, a somewhat clunky yet powerful interface to build result collections both sequential (by adding single elements) and in parallel (by combining multiple elements via addAll).

This Method can also be used with guava-collections by defining its own collector based on ImmutableCollection.Builder, but there is one catch:
The Collector-Interface requires at least the following:

  • a Supplier: Builder::new
  • an Accumulator: Builder::add
  • a Combiner Builder::addAll
  • a finisher: Builder::build

The problem is the addAll-Method: In Order to be compatible with the Combiner, it needs to take a Builder as its ínput. However, the Builder.addAll methods currently only allows it to add Iterables, not another builder. So the accumulator-function would be something like builder.addAll(otherBuilder.build()), which is not very efficient, especially for Set-Builders.


There are at least three different ways to solve this problem:

  • Make the Builder itself Iterable, so that it can be added to its own addAll-Method.
  • Add another addAll-Method overload to ImmutableCollection.Builder which accepts any ImmutableCollection.Builder.
  • Accept the overhead until guava is JDK8-ready, then roll your own Collector which can access the package-private internal structure of the builder.
@gissuebot
Copy link
Author

Original comment posted by cgdecker@google.com on 2013-11-18 at 05:53 PM


A Java 8 version of Guava is a long ways off at this point, as Guava currently still targets Java 6. Java 8 will also require major changes to Guava given that many new things it provides are similar or equivalent to things in Guava.

This is definitely something that's on our radar for things we do want to add, though. It probably wouldn't be in the form of a change to any of the ImmutableCollection Builders, but just a new set of Collectors for creating ImmutableCollections.


Status: Research
Labels: Package-Collect, Type-Addition

@gissuebot
Copy link
Author

Original comment posted by lowasser@google.com on 2013-11-18 at 10:28 PM


FWIW, even today you can use Collectors.collectingAndThen(Collectors.toList(), ImmutableList::copyOf), which is not at all an unreasonable implementation generally speaking.

@gissuebot
Copy link
Author

Original comment posted by sim.herter on 2014-08-18 at 08:25 PM


Is there any reason to favor stream.collect(Collectors.collectingAndThen(Collectors.toList(), ImmutableList::copyOf) ) over ImmutableList.copyOf(stream.iterator())?
The first one seems to be a more functional approach (and I looove programming in functional style with JDK8!), but since I see this a lot in my code I think I would prefer the shorter one if nothing technical speaks against it.

@gissuebot
Copy link
Author

Original comment posted by lowasser@google.com on 2014-08-18 at 08:28 PM


The former would probably work better if your stream is parallel, and I don't think it's any less efficient in general.

@bacar
Copy link

bacar commented Nov 6, 2014

The first two suggestions, repeated below, could be done to help support Java 8 users without needing "a Java 8 version of Guava" (or at least what I choose to interpret from that statement, anyway) - is there a philosophical (or otherwise) objection to folding that in?

  • Make the Builder itself Iterable, so that it can be added to its own addAll-Method.
  • Add another addAll-Method overload to ImmutableCollection.Builder which accepts any ImmutableCollection.Builder.

@justinuang
Copy link

I was wondering, why is stream.collect(Collectors.collectingAndThen(Collectors.toList(), ImmutableList::copyOf)) the same efficiency as ImmutableList.copyOf(stream.iterator())?

It sounds like the first approach requires building an array, then copying the array into an ImmutableList whereas the second approach only builds the array once.

@lowasser
Copy link
Contributor

Both approaches are going to put the stream into a ArrayList-like structure, and then copy it into the ImmutableList. ImmutableList.copyOf(Iterator) delegates to ImmutableList.Builder, which is built as approximately a specialized ArrayList.

@justinuang
Copy link

I see, thanks for the help =)

@kilink
Copy link

kilink commented Aug 27, 2015

I don't think that's 100% true. ImmutableList.copyOf(stream.iterator()) is more efficient for the special case of an iterator yielding only 0 or 1 elements, where it avoids allocating the intermediary ArrayList.

@kluever
Copy link
Member

kluever commented Oct 15, 2015

We have a plan we're working on to use collectors w/ immutable collections and it'll be addresses in an upcoming version of Guava that supports Java8.

@Helmsdown
Copy link

+1

@dotCipher
Copy link

Would love to see this added into the core guava codebase. Any traction on this yet?

@lowasser
Copy link
Contributor

lowasser commented Jan 9, 2017

The immutable collections now have built-in collectors that will be included in the Guava 21 release. I think we can actually call this closed?

(We haven't exposed collector-ness in the builders themselves, just collectors, but I think that's what we'd prefer unless we hear compelling reasons to add them into the builders.)

@lowasser lowasser closed this as completed Jan 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants