createCars() {
+ return Arrays.asList(new Car("Jeep", "Wrangler", 2011, Category.JEEP),
+ new Car("Jeep", "Comanche", 1990, Category.JEEP),
+ new Car("Dodge", "Avenger", 2010, Category.SEDAN),
+ new Car("Buick", "Cascada", 2016, Category.CONVERTIBLE),
+ new Car("Ford", "Focus", 2012, Category.SEDAN),
+ new Car("Chevrolet", "Geo Metro", 1992, Category.CONVERTIBLE));
+ }
+}
\ No newline at end of file
diff --git a/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/Category.java b/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/Category.java
new file mode 100644
index 000000000..456864fdb
--- /dev/null
+++ b/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/Category.java
@@ -0,0 +1,30 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.collectionpipeline;
+
+/**
+ * Enum for the category of car
+ */
+public enum Category {
+ JEEP, SEDAN, CONVERTIBLE
+}
diff --git a/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/FunctionalProgramming.java b/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/FunctionalProgramming.java
new file mode 100644
index 000000000..3cc24ce44
--- /dev/null
+++ b/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/FunctionalProgramming.java
@@ -0,0 +1,84 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.collectionpipeline;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Iterating and sorting with a collection pipeline
+ *
+ * In functional programming, it's common to sequence complex operations through
+ * a series of smaller modular functions or operations. The series is called a
+ * composition of functions, or a function composition. When a collection of
+ * data flows through a function composition, it becomes a collection pipeline.
+ * Function Composition and Collection Pipeline are two design patterns
+ * frequently used in functional-style programming.
+ *
+ *
Instead of passing a lambda expression to the map method, we passed the
+ * method reference Car::getModel. Likewise, instead of passing the lambda
+ * expression car -> car.getYear() to the comparing method, we passed the method
+ * reference Car::getYear. Method references are short, concise, and expressive.
+ * It is best to use them wherever possible.
+ *
+ */
+public class FunctionalProgramming {
+ private FunctionalProgramming() {
+ }
+
+ /**
+ * Method to get models using for collection pipeline.
+ *
+ * @param cars {@link List} of {@link Car} to be used for filtering
+ * @return {@link List} of {@link String} representing models built after year 2000
+ */
+ public static List getModelsAfter2000(List cars) {
+ return cars.stream().filter(car -> car.getYear() > 2000)
+ .sorted(Comparator.comparing(Car::getYear))
+ .map(Car::getModel).collect(Collectors.toList());
+ }
+
+ /**
+ * Method to group cars by category using groupingBy
+ *
+ * @param cars {@link List} of {@link Car} to be used for grouping
+ * @return {@link Map} with category as key and cars belonging to that category as value
+ */
+ public static Map> getGroupingOfCarsByCategory(List cars) {
+ return cars.stream().collect(Collectors.groupingBy(Car::getCategory));
+ }
+
+ /**
+ * Method to get all Sedan cars belonging to a group of persons sorted by year of manufacture
+ *
+ * @param persons {@link List} of {@link Person} to be used
+ * @return {@link List} of {@link Car} to belonging to the group
+ */
+ public static List getSedanCarsOwnedSortedByDate(List persons) {
+ return persons.stream().map(Person::getCars).flatMap(List::stream)
+ .filter(car -> Category.SEDAN.equals(car.getCategory()))
+ .sorted(Comparator.comparing(Car::getYear)).collect(Collectors.toList());
+ }
+}
diff --git a/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/ImperativeProgramming.java b/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/ImperativeProgramming.java
new file mode 100644
index 000000000..7466462cc
--- /dev/null
+++ b/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/ImperativeProgramming.java
@@ -0,0 +1,131 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.collectionpipeline;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Imperative-style programming to iterate over the list and get the names of
+ * cars made later than the year 2000. We then sort the models in ascending
+ * order by year.
+ *
+ * As you can see, there's a lot of looping in this code. First, the
+ * getModelsAfter2000UsingFor method takes a list of cars as its parameter. It
+ * extracts or filters out cars made after the year 2000, putting them into a
+ * new list named carsSortedByYear. Next, it sorts that list in ascending order
+ * by year-of-make. Finally, it loops through the list carsSortedByYear to get
+ * the model names and returns them in a list.
+ *
+ *
This short example demonstrates what I call the effect of statements. While
+ * functions and methods in general can be used as expressions, the {@link Collections}
+ * sort method doesn't return a result. Because it is used as a statement, it
+ * mutates the list given as argument. Both of the for loops also mutate lists
+ * as they iterate. Being statements, that's just how these elements work. As a
+ * result, the code contains unnecessary garbage variables
+ */
+public class ImperativeProgramming {
+ private ImperativeProgramming() {
+ }
+
+ /**
+ * Method to return the car models built after year 2000 using for loops.
+ * @param cars {@link List} of {@link Car} to iterate over
+ * @return {@link List} of {@link String} of car models built after year 2000
+ */
+ public static List getModelsAfter2000(List cars) {
+ List carsSortedByYear = new ArrayList<>();
+
+ for (Car car : cars) {
+ if (car.getYear() > 2000) {
+ carsSortedByYear.add(car);
+ }
+ }
+
+ Collections.sort(carsSortedByYear, new Comparator() {
+ public int compare(Car car1, Car car2) {
+ return new Integer(car1.getYear()).compareTo(car2.getYear());
+ }
+ });
+
+ List models = new ArrayList<>();
+ for (Car car : carsSortedByYear) {
+ models.add(car.getModel());
+ }
+
+ return models;
+ }
+
+ /**
+ * Method to group cars by category using for loops
+ *
+ * @param cars {@link List} of {@link Car} to be used for grouping
+ * @return {@link Map} with category as key and cars belonging to that category as value
+ */
+ public static Map> getGroupingOfCarsByCategory(List cars) {
+ Map> groupingByCategory = new HashMap<>();
+ for (Car car: cars) {
+ if (groupingByCategory.containsKey(car.getCategory())) {
+ groupingByCategory.get(car.getCategory()).add(car);
+ } else {
+ List categoryCars = new ArrayList<>();
+ categoryCars.add(car);
+ groupingByCategory.put(car.getCategory(), categoryCars);
+ }
+ }
+ return groupingByCategory;
+ }
+
+ /**
+ * Method to get all Sedan cars belonging to a group of persons sorted by year of manufacture using for loops
+ *
+ * @param persons {@link List} of {@link Person} to be used
+ * @return {@link List} of {@link Car} to belonging to the group
+ */
+ public static List getSedanCarsOwnedSortedByDate(List persons) {
+ List cars = new ArrayList<>();
+ for (Person person: persons) {
+ cars.addAll(person.getCars());
+ }
+
+ List sedanCars = new ArrayList<>();
+ for (Car car: cars) {
+ if (Category.SEDAN.equals(car.getCategory())) {
+ sedanCars.add(car);
+ }
+ }
+
+ sedanCars.sort(new Comparator() {
+ @Override
+ public int compare(Car o1, Car o2) {
+ return o1.getYear() - o2.getYear();
+ }
+ });
+
+ return sedanCars;
+ }
+}
diff --git a/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/Person.java b/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/Person.java
new file mode 100644
index 000000000..c9114c125
--- /dev/null
+++ b/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/Person.java
@@ -0,0 +1,44 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.collectionpipeline;
+
+import java.util.List;
+
+/**
+ * A Person class that has the list of cars that the person owns and use.
+ */
+public class Person {
+ private List cars;
+
+ /**
+ * Constructor to create an instance of person.
+ * @param cars the list of cars owned
+ */
+ public Person(List cars) {
+ this.cars = cars;
+ }
+
+ public List getCars() {
+ return cars;
+ }
+}
\ No newline at end of file
diff --git a/collection-pipeline/src/test/java/com/iluwatar/collectionpipeline/AppTest.java b/collection-pipeline/src/test/java/com/iluwatar/collectionpipeline/AppTest.java
new file mode 100644
index 000000000..5a6821641
--- /dev/null
+++ b/collection-pipeline/src/test/java/com/iluwatar/collectionpipeline/AppTest.java
@@ -0,0 +1,79 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.collectionpipeline;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests that Collection Pipeline methods work as expected.
+ */
+public class AppTest {
+
+ private List cars = CarFactory.createCars();
+
+ @Test
+ public void testGetModelsAfter2000UsingFor() {
+ List models = ImperativeProgramming.getModelsAfter2000(cars);
+ assertEquals(Arrays.asList("Avenger", "Wrangler", "Focus", "Cascada"), models);
+ }
+
+ @Test
+ public void testGetModelsAfter2000UsingPipeline() {
+ List models = FunctionalProgramming.getModelsAfter2000(cars);
+ assertEquals(Arrays.asList("Avenger", "Wrangler", "Focus", "Cascada"), models);
+ }
+
+ @Test
+ public void testGetGroupingOfCarsByCategory() {
+ Map> modelsExpected = new HashMap<>();
+ modelsExpected.put(Category.CONVERTIBLE, Arrays.asList(new Car("Buick", "Cascada", 2016, Category.CONVERTIBLE),
+ new Car("Chevrolet", "Geo Metro", 1992, Category.CONVERTIBLE)));
+ modelsExpected.put(Category.SEDAN, Arrays.asList(new Car("Dodge", "Avenger", 2010, Category.SEDAN),
+ new Car("Ford", "Focus", 2012, Category.SEDAN)));
+ modelsExpected.put(Category.JEEP, Arrays.asList(new Car("Jeep", "Wrangler", 2011, Category.JEEP),
+ new Car("Jeep", "Comanche", 1990, Category.JEEP)));
+ Map> modelsFunctional = FunctionalProgramming.getGroupingOfCarsByCategory(cars);
+ Map> modelsImperative = ImperativeProgramming.getGroupingOfCarsByCategory(cars);
+ System.out.println("Category " + modelsFunctional);
+ assertEquals(modelsExpected, modelsFunctional);
+ assertEquals(modelsExpected, modelsImperative);
+ }
+
+ @Test
+ public void testGetSedanCarsOwnedSortedByDate() {
+ Person john = new Person(cars);
+ List modelsExpected = Arrays.asList(new Car("Dodge", "Avenger", 2010, Category.SEDAN),
+ new Car("Ford", "Focus", 2012, Category.SEDAN));
+ List modelsFunctional = FunctionalProgramming.getSedanCarsOwnedSortedByDate(Arrays.asList(john));
+ List modelsImperative = ImperativeProgramming.getSedanCarsOwnedSortedByDate(Arrays.asList(john));
+ assertEquals(modelsExpected, modelsFunctional);
+ assertEquals(modelsExpected, modelsImperative);
+ }
+}
diff --git a/pom.xml b/pom.xml
index 81763b6c1..322aadb8b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -162,7 +162,8 @@
trampoline
serverless
ambassador
- acyclic-visitor
+ acyclic-visitor
+ collection-pipeline
@@ -478,4 +479,4 @@
-
+
\ No newline at end of file