A couple of tabulate/Tabulators.groupBy examples

Brian Goetz brian.goetz at oracle.com
Wed Dec 26 10:49:26 PST 2012


> A simple example.
>
> Before:
>
> 	Map<String, Collection<Customer>> multimap = this.company.getCustomers().stream().groupBy(Customer::getCity);
>
> After:
>
>        Map<String, Collection<Customer>> multimap =
>              this.company.getCustomers()
>                  .stream()
>                  .tabulate(Tabulators.<Customer, String>groupBy(Customer::getCity));

I would think the explicit arguments in this case could be avoided? 
Usually we've only had problems with inference when there are 
constructor refs (ArrayList::new).  In any case, there's work going on 
to improve inference here.

With properly working inference and static import we'd get:

 >              this.company.getCustomers()
 >                  .stream()
 >                  .tabulate(groupBy(Customer::getCity));

Where the Tabulators stuff really shines is the ability to compose these 
things.  The old groupBy/reduceBy did a decent job at what it did well, 
but fell off a cliff when you asked it to do much more.

> A more complex example.

This is kind of a weird example, since the synthetic key is a number.

Another way to accomplish this, that might be more in line with real 
business usage, is by the equivalent of the old "mapped":

Map<Customer, Double> largestLineItemByByCustomer =
   customers.stream().tabulate(mappedTo(c -> c.getOrders()...reduce()));

This creates a map from Customer to your max order value reduction.  If 
you then want a "top ten customers by largest transaction", you could do:

   largestLineItemByCustomer.entrySet()
                            .stream()
                            .sorted(Comparators.naturalOrderValues())
                            .limit(10)
                            .map(Map.Entry::getKey)
                            .forEach(...);



>
> Before:
>
>         Map<Double, Collection<Customer>> multimap = this.company.getCustomers()
>             .stream()
>             .groupBy(customer ->
>                 customer.getOrders()
>                     .stream()
>                     .flatMap((Block<? super LineItem> sink, Order element) -> {element.getLineItems().forEach(sink);})
>                     .map(LineItem::getValue)
>                     .reduce(0.0, (x, y) -> Math.max(x,y)));


More information about the lambda-libs-spec-observers mailing list