--- /dev/null 2014-02-05 01:06:16.000000000 +0800 +++ new/src/share/sample/stream/Grouping.java 2014-02-05 01:06:15.372211000 +0800 @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This source code is provided to illustrate the usage of a given feature + * or technique and has been deliberately simplified. Additional steps + * required for a production-quality application, such as security checks, + * input validation and proper error handling, might not be present in + * this sample code. + */ +package stream; + +import stream.data.Customer; +import stream.data.Product; +import stream.data.Order; +import java.util.ArrayList; +import java.util.Comparator; +import static java.util.Comparator.*; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.stream.Collector; +import java.util.stream.Collectors; +import static java.util.stream.Collectors.*; +import java.util.stream.Stream; + +/** + * This class demos shows usage of group Collector working with collect method. + * + * @author tyan + */ +public class Grouping extends DemoHelper { + + /** + * Group products by T + * + * @param byXXX a function which convert Product to T + * @return a map between T object to a product list, any product in this + * list using byXXX conversion is same to map's key + */ + + public static Map> groupProduct( + Function byXXX) { + return products.stream(). + //grouping product by given function + collect(groupingBy(byXXX)); + } + + /** + * Group orders by customer with using Collectors.groupingBy(Function, + * Collector) + * + * @return map customer to its order list + */ + public static Map> groupOrdersByCustomer() { + //a collector that generate a order list from a customer + Collector, List> collectOrder = Collector. + of(ArrayList::new, + (orders, customer) -> { + orders.addAll(customer.getOrders()); + }, + (left, right) -> { + left.addAll(right); + return left; + }); + return customers.stream(). + //convert customers to a Map which key is it name, value is its + //orders + collect(groupingBy(Customer::getCompanyName, + collectOrder)); + } + + /** + * Group products by categories, only select max/min value of product + * ordered by compFunc + * + * @param maxBy true select max value product false select min value product + * @param groupFunc function provides how to group product + * @param compFunc function provides how to sort product + * @return a map between a instance of S to instance of T + */ + public static > Map> + productMaxByTGroupByS(boolean maxBy, Function groupFunc, + Function compFunc) { + //Comparator of Product which will compare on T by given function + Comparator comp = comparing(compFunc); + //A collector that collet maximal or minimal element according to a + //given maxBy and Comparator + Collector> collector + = maxBy ? maxBy(comp) : minBy(comp); + return products.stream(). + //collect products into a Map, which key is S by function of + //groupFunc, value is max or min by given max and function of + //compFunc + collect(Collectors.groupingBy(groupFunc, collector)); + } + + /** + * Group products by R, this is demo for grouping by different element one + * by one. + * + * @param func1 function that convert Product to R + * @param func2 function that convert Product to T + * @return a map which groups products to R then T + */ + public static Map>> ordersByRThenT( + Function func1, Function func2) { + return customers.stream().collect( + streaming(customer -> customer.getOrders().stream(), + groupingBy(func1, groupingBy(func2)))); + } + + /** + * A downstream collector that streams elements to a further downstream + * collector. + * + * @param the type of the input elements + * @param the supplier type of the downstream collector + * @param the intermediate accumulation type of the downstream collector + * @param the result type of the downstream reduction + * @param mapper the classifier function mapping input elements to object of + * U + * @param downstream a collector implementing the downstream reduction + * @return a collector convert element to other object followed by an + * downstream a collector which performs the action + */ + public static + Collector streaming(Function> mapper, + Collector downstream) { + BiConsumer downstreamAccumulator = downstream.accumulator(); + return Collector.of(downstream.supplier(), + (r, t) -> mapper.apply(t).sequential().forEach( + u -> downstreamAccumulator.accept(r, u)), + downstream.combiner(), + downstream.finisher(), + downstream.characteristics().stream().toArray( + Collector.Characteristics[]::new)); + } + +}