Skip to content

Commit 2c8d174

Browse files
committed
iluwatar#564: Collection Pipeline pattern
1 parent 987994f commit 2c8d174

File tree

11 files changed

+490
-0
lines changed

11 files changed

+490
-0
lines changed

collection-pipeline/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
layout: pattern
3+
title: Collection Pipeline
4+
folder: collection-pipeline
5+
permalink: /patterns/collection-pipeline/
6+
categories: Functional
7+
tags:
8+
- Java
9+
- Difficulty-Beginner
10+
- Functional
11+
---
12+
13+
## Intent
14+
Collection Pipeline introduces Function Composition and Collection Pipeline, two functional-style patterns that you can combine to iterate collections in your code.
15+
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.
16+
17+
![alt text](./etc/collection-pipeline.png "Collection Pipeline")
18+
19+
## Applicability
20+
Use the Collection Pipeline pattern when
21+
22+
* When you want to perform a sequence of operations where one operation's collected output is fed into the next
23+
* When you use a lot of statements in your code
24+
* When you use a lot of loops in your code
25+
26+
## Credits
27+
28+
* [Function composition and the Collection Pipeline pattern](https://www.ibm.com/developerworks/library/j-java8idioms2/index.html)
29+
* [Martin Fowler](https://martinfowler.com/articles/collection-pipeline/)
14.2 KB
Loading
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<class-diagram version="1.2.2" icons="true" always-add-relationships="false" generalizations="true" realizations="true"
3+
associations="true" dependencies="false" nesting-relationships="true" router="FAN">
4+
<class id="1" language="java" name="com.iluwatar.collectionpipeline.App" project="collection-pipeline"
5+
file="/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/App.java" binary="false"
6+
corner="BOTTOM_RIGHT">
7+
<position height="-1" width="-1" x="952" y="278"/>
8+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
9+
sort-features="false" accessors="true" visibility="true">
10+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
11+
<operations public="true" package="true" protected="true" private="true" static="true"/>
12+
</display>
13+
</class>
14+
<class id="2" language="java" name="com.iluwatar.collectionpipeline.ImperativeProgramming"
15+
project="collection-pipeline"
16+
file="/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/ImperativeProgramming.java" binary="false"
17+
corner="BOTTOM_RIGHT">
18+
<position height="-1" width="-1" x="552" y="107"/>
19+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
20+
sort-features="false" accessors="true" visibility="true">
21+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
22+
<operations public="true" package="true" protected="true" private="true" static="true"/>
23+
</display>
24+
</class>
25+
<class id="3" language="java" name="com.iluwatar.collectionpipeline.Car" project="collection-pipeline"
26+
file="/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/Car.java" binary="false"
27+
corner="BOTTOM_RIGHT">
28+
<position height="-1" width="-1" x="476" y="301"/>
29+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
30+
sort-features="false" accessors="true" visibility="true">
31+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
32+
<operations public="true" package="true" protected="true" private="true" static="true"/>
33+
</display>
34+
</class>
35+
<class id="4" language="java" name="com.iluwatar.collectionpipeline.FunctionalProgramming"
36+
project="collection-pipeline"
37+
file="/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/FunctionalProgramming.java" binary="false"
38+
corner="BOTTOM_RIGHT">
39+
<position height="-1" width="-1" x="914" y="105"/>
40+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
41+
sort-features="false" accessors="true" visibility="true">
42+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
43+
<operations public="true" package="true" protected="true" private="true" static="true"/>
44+
</display>
45+
</class>
46+
<class id="5" language="java" name="com.iluwatar.collectionpipeline.Iterating" project="collection-pipeline"
47+
file="/collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/Iterating.java" binary="false"
48+
corner="BOTTOM_RIGHT">
49+
<position height="-1" width="-1" x="723" y="280"/>
50+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
51+
sort-features="false" accessors="true" visibility="true">
52+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
53+
<operations public="true" package="true" protected="true" private="true" static="true"/>
54+
</display>
55+
</class>
56+
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
57+
sort-features="false" accessors="true" visibility="true">
58+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
59+
<operations public="true" package="true" protected="true" private="true" static="true"/>
60+
</classifier-display>
61+
<association-display labels="true" multiplicity="true"/>
62+
</class-diagram>

collection-pipeline/pom.xml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!--
2+
3+
The MIT License
4+
Copyright (c) 2014 Ilkka Seppälä
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in
14+
all copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
THE SOFTWARE.
23+
24+
-->
25+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
26+
<modelVersion>4.0.0</modelVersion>
27+
<parent>
28+
<groupId>com.iluwatar</groupId>
29+
<artifactId>java-design-patterns</artifactId>
30+
<version>1.20.0-SNAPSHOT</version>
31+
</parent>
32+
<artifactId>collection-pipeline</artifactId>
33+
<dependencies>
34+
<dependency>
35+
<groupId>org.junit.jupiter</groupId>
36+
<artifactId>junit-jupiter-api</artifactId>
37+
<scope>test</scope>
38+
</dependency>
39+
<dependency>
40+
<groupId>org.junit.jupiter</groupId>
41+
<artifactId>junit-jupiter-engine</artifactId>
42+
<scope>test</scope>
43+
</dependency>
44+
</dependencies>
45+
</project>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2014 Ilkka Seppälä
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package com.iluwatar.collectionpipeline;
24+
25+
import java.util.List;
26+
27+
import org.slf4j.Logger;
28+
import org.slf4j.LoggerFactory;
29+
30+
/**
31+
* In imperative-style programming, it is common to use for and while loops for
32+
* most kinds of data processing. Function composition is a simple technique
33+
* that lets you sequence modular functions to create more complex operations.
34+
* When you run data through the sequence, you have a collection pipeline.
35+
* Together, the Function Composition and Collection Pipeline patterns enable
36+
* you to create sophisticated programs where data flow from upstream to
37+
* downstream and is passed through a series of transformations.
38+
*
39+
*/
40+
public class App {
41+
42+
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
43+
44+
/**
45+
* Program entry point.
46+
*
47+
* @param args
48+
* command line args
49+
*/
50+
public static void main(String[] args) {
51+
52+
List<Car> cars = Iterating.createCars();
53+
54+
List<String> modelsImperative = ImperativeProgramming.getModelsAfter2000UsingFor(cars);
55+
LOGGER.info(modelsImperative.toString());
56+
57+
List<String> modelsFunctional = FunctionalProgramming.getModelsAfter2000UsingPipeline(cars);
58+
LOGGER.info(modelsFunctional.toString());
59+
}
60+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2014 Ilkka Seppälä
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package com.iluwatar.collectionpipeline;
24+
25+
/**
26+
* A Car class that has the properties of make, model, and year.
27+
*/
28+
public class Car {
29+
private String make;
30+
private String model;
31+
private int year;
32+
33+
/**
34+
* Constructor to create an instance of car.
35+
* @param theMake the make of the car
36+
* @param theModel the model of the car
37+
* @param yearOfMake the year of built of the car
38+
*/
39+
public Car(String theMake, String theModel, int yearOfMake) {
40+
make = theMake;
41+
model = theModel;
42+
year = yearOfMake;
43+
}
44+
45+
public String getMake() {
46+
return make;
47+
}
48+
49+
public String getModel() {
50+
return model;
51+
}
52+
53+
public int getYear() {
54+
return year;
55+
}
56+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2014 Ilkka Seppälä
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package com.iluwatar.collectionpipeline;
24+
25+
import java.util.Comparator;
26+
import java.util.List;
27+
import java.util.stream.Collectors;
28+
29+
/**
30+
* Iterating and sorting with a collection pipeline
31+
*
32+
* <p>In functional programming, it's common to sequence complex operations through
33+
* a series of smaller modular functions or operations. The series is called a
34+
* composition of functions, or a function composition. When a collection of
35+
* data flows through a function composition, it becomes a collection pipeline.
36+
* Function Composition and Collection Pipeline are two design patterns
37+
* frequently used in functional-style programming.
38+
*
39+
* <p>Instead of passing a lambda expression to the map method, we passed the
40+
* method reference Car::getModel. Likewise, instead of passing the lambda
41+
* expression car -> car.getYear() to the comparing method, we passed the method
42+
* reference Car::getYear. Method references are short, concise, and expressive.
43+
* It is best to use them wherever possible.
44+
*
45+
*/
46+
public class FunctionalProgramming {
47+
private FunctionalProgramming() {
48+
}
49+
50+
/**
51+
* Method to get models using for collection pipeline.
52+
*
53+
* @param cars {@link List} of {@link Car} to be used for filtering
54+
* @return {@link List} of {@link String} representing models built after year 2000
55+
*/
56+
public static List<String> getModelsAfter2000UsingPipeline(List<Car> cars) {
57+
return cars.stream().filter(car -> car.getYear() > 2000)
58+
.sorted(Comparator.comparing(Car::getYear))
59+
.map(Car::getModel).collect(Collectors.toList());
60+
}
61+
}

0 commit comments

Comments
 (0)