Options to accumulate from a List without an intermediate

Arul Dhesiaseelan aruld at acm.org
Fri Jan 4 21:10:31 PST 2013


Excellent!

Here are the working versions. I had to cast to MultiFunction<Album, Track>
and apply Accumulators.<Track, Integer> before groupBy to break cyclic
inference, as it failed to compile because of java: incompatible types:
Cannot instantiate inference variables T because of an inference loop.

#1
final List<Track> tracks = albums.stream().mapMulti((MultiFunction<Album,
Track>) (collector, element) -> collector.yield(element.tracks)).into(new
ArrayList<Track>());

#2
Map<Integer, Collection<Track>> tracksByRating =
albums.stream().mapMulti((MultiFunction<Album, Track>) (collector, element)
-> collector.yield(element.tracks)).accumulate(Accumulators.<Track,
Integer>groupBy(Track::getRating));

Thanks Brian!

On Fri, Jan 4, 2013 at 5:53 PM, Brian Goetz <brian.goetz at oracle.com> wrote:

> Currently you can do:
>
>   albums.stream()
>         .mapMulti((d, a) -> d.yield(a.tracks))
>         .into(new ArrayList<>());
>
> It is likely into() is replaced with some sort of aggregate:
>
>   albums.stream()
>         .mapMulti((d, a) -> d.yield(a.tracks))
>         .aggregate(intoList());
>
> which covers your first case.
>
> To group by rating, you can do:
>
> Map<Integer, Collection<Track>>
>   albums.stream()
>         .mapMulti((d, a) -> d.yield(a.tracks))
>         .accumulate(groupBy(Track::getRating));
>
>
>
> On 1/4/2013 10:19 PM, Arul Dhesiaseelan wrote:
>
>> Is there a better way to accumulate tracks from an album, without using an
>> intermediate?
>>
>> Take1 uses an intermediate, while Take2 does not use one, but more
>> verbose.
>> May be there is a better way?
>>
>> Take#1
>>      final List<Track> tracks = new ArrayList<>();
>>      albums.stream().forEach(album -> tracks.addAll(album.tracks));
>>
>>      // Group album tracks by rating
>>      Map<Integer, Collection<Track>> tracksByRating =
>> tracks.stream().accumulate(Accumulators.<Track,
>> Integer>groupBy(Track::getRating));
>>
>> Take#2
>>      Map<Integer, Collection<Track>> tracksByRating =
>> albums.stream().accumulate(new Accumulator<Album, List<Track>>() {
>>        @Override
>>        public List<Track> makeResult() {
>>          return new ArrayList<>();
>>        }
>>
>>        @Override
>>        public void accumulate(List<Track> result, Album value) {
>>          result.addAll(value.tracks);
>>        }
>>
>>        @Override
>>        public List<Track> combine(List<Track> result, List<Track> other) {
>>          return Streams.concat(result.stream(), other.stream()).into(new
>> ArrayList<Track>());
>>        }
>>      }).stream().accumulate(Accumulators.<Track,
>> Integer>groupBy(Track::getRating));
>>
>>
>> Thanks!
>> Arul
>>
>>


More information about the lambda-dev mailing list