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