1 /*
   2  * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  *
   8  *   - Redistributions of source code must retain the above copyright
   9  *     notice, this list of conditions and the following disclaimer.
  10  *
  11  *   - Redistributions in binary form must reproduce the above copyright
  12  *     notice, this list of conditions and the following disclaimer in the
  13  *     documentation and/or other materials provided with the distribution.
  14  *
  15  *   - Neither the name of Oracle nor the names of its
  16  *     contributors may be used to endorse or promote products derived
  17  *     from this software without specific prior written permission.
  18  *
  19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30  */
  31 
  32 /*
  33  * This source code is provided to illustrate the usage of a given feature
  34  * or technique and has been deliberately simplified. Additional steps
  35  * required for a production-quality application, such as security checks,
  36  * input validation and proper error handling, might not be present in
  37  * this sample code.
  38  */
  39 package stream;
  40 
  41 import stream.data.Vendor;
  42 import stream.data.Product;
  43 import java.util.Map;
  44 import java.util.Optional;
  45 import java.util.function.BinaryOperator;
  46 import static java.util.stream.Collectors.*;
  47 import java.util.stream.Stream;
  48 
  49 /**
  50  * This class demos find operation that attach to collection, findFirst returns
  51  * first element in the stream, it's reasonable we can expect it's the first
  52  * element in the collection if collection is ordered. On the contrary, findAny
  53  * returns any element in the stream.
  54  *
  55  * @author tyan
  56  */
  57 public class Elements extends DemoHelper {
  58 
  59     /**
  60      * Find any vendor or first vendor in country, this demos how implement a
  61      * simple find on a source with one condition
  62      *
  63      * @param findAny true perform findAny on stream false perform findFirst on
  64      * stream
  65      * @param country vendor's country
  66      * @return any/first vendor in given country
  67      */
  68 
  69     public static Optional<Vendor> vendorsInCountry(boolean findAny,
  70             String country) {
  71         Stream<Vendor> s = vendors.stream().
  72                 //filter vendor who is same sa given country
  73                 filter(vendor -> country.
  74                         equals(vendor.getCountry()));
  75 
  76         return findAny ? s.findAny() : s.findFirst();
  77     }
  78 
  79     /**
  80      * Get mapping table between category to any/first in-stock product.
  81      *
  82      * @param findAny true perform findAny on stream false perform findFirst on
  83      * stream
  84      * @return a map mapping every category to any/first in-stock product
  85      */
  86     public static Map<String, Product> inStockProductsByCategory(
  87             boolean findAny) {
  88         //A BinaryOperator only select first non-null element
  89         BinaryOperator<Product> reduceToFirstMatch = (l, r) -> (l != null)
  90                 ? l : (r != null && r.getUnitsInStock() > 0)
  91                 ? r : null;
  92 
  93         //grouping products by category, pick first element in same category
  94         return products.stream().collect(
  95                 groupingBy(Product::getCategory,
  96                         reducing(null, reduceToFirstMatch)));
  97     }
  98 }