--- /dev/null 2014-02-02 21:38:48.000000000 +0800 +++ new/src/share/sample/stream/Tabulate.java 2014-02-02 21:38:48.000000000 +0800 @@ -0,0 +1,98 @@ +/* + * 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.Vendor; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import static java.util.stream.Collectors.*; +import java.util.stream.Stream; + +/** + * A demo shows how does Stream's flatMap works. Demo shows tabulate stream + * element to single element stream or empty stream + * + * @author tyan + */ +public class Tabulate extends DemoHelper { + /** + * Join vendor and customer that in same country. note not all vendor + * has customer + * @return a list of customer-vendor pair which in same country + */ + public static Map> sameCountryCustomerAndVendors() { + Map> countryToVendors = vendors.stream(). + // group vendors by their country + collect(groupingBy(Vendor::getCountry)); + //Find customer in countryToVendors with key as customer's country + Function> vendorsInSameCustomerCountry + = customer-> countryToVendors.getOrDefault( + customer.getCountry(), new ArrayList<>()); + //Map customer to vendor who are same country as customer's + return customers.stream(). + filter(c -> countryToVendors.containsKey(c.getCountry())). + collect(toMap(Function.identity(), vendorsInSameCustomerCountry)); + } + + /** + * flatMap can generate empty stream, sometimes it's helpful for ruling + * out data + * @return a string set who is either customer and vendor both. + */ + public static Set bothCustomerAndVendor() { + Set vendorsName = vendors.stream(). + map(Vendor::getVendorName). + collect(toSet()); + return customers.stream(). + //map customer to its name + map(Customer::getCompanyName). + //query vendor set with customer's name, if exist, create + //a stream with single element customer name, if doesn't, create + //an empty stream + flatMap(c -> vendorsName.contains(c) + ? Stream.of(c) : Stream.empty()). + //convert all match name into a set + collect(Collectors.toSet()); + } +}