diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml
new file mode 100644
index 000000000..c78c182e3
--- /dev/null
+++ b/fluentinterface/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ java-design-patterns
+ com.iluwatar
+ 1.5.0
+
+ 4.0.0
+
+ fluentinterface
+
+
+ junit
+ junit
+ test
+
+
+
\ No newline at end of file
diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/App.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/App.java
new file mode 100644
index 000000000..fded13624
--- /dev/null
+++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/App.java
@@ -0,0 +1,90 @@
+package com.iluwatar.fluentinterface;
+
+import com.iluwatar.fluentinterface.fluentiterable.FluentIterable;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringJoiner;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+public class App {
+
+ public static void main(String[] args) {
+
+ List integerList = new ArrayList() {{
+ add(1);
+ add(-61);
+ add(14);
+ add(-22);
+ add(18);
+ add(-87);
+ add(6);
+ add(64);
+ add(-82);
+ add(26);
+ add(-98);
+ add(97);
+ add(45);
+ add(23);
+ add(2);
+ add(-68);
+ add(45);
+ }};
+ prettyPrint("The initial list contains: ", integerList);
+
+ List firstFiveNegatives = FluentIterable.from(integerList)
+ .filter(negatives())
+ .first(3)
+ .asList();
+ prettyPrint("The first three negative values are: ", firstFiveNegatives);
+
+
+ List lastTwoPositives = FluentIterable.from(integerList)
+ .filter(positives())
+ .last(2)
+ .asList();
+ prettyPrint("The last two positive values are: ", lastTwoPositives);
+
+ FluentIterable.from(integerList)
+ .filter(number -> number%2 == 0)
+ .first()
+ .ifPresent(evenNumber -> System.out.println(String.format("The first even number is: %d", evenNumber)));
+
+
+ List transformedList = FluentIterable.from(integerList)
+ .filter(negatives())
+ .map(transformToString())
+ .asList();
+ prettyPrint("A string-mapped list of negative numbers contains: ", transformedList);
+
+ }
+
+ private static Function transformToString() {
+ return integer -> "String[" + String.valueOf(integer) + "]";
+ }
+ private static Predicate super Integer> negatives() {
+ return integer -> (integer < 0);
+ }
+ private static Predicate super Integer> positives() {
+ return integer -> (integer > 0);
+ }
+
+ private static void prettyPrint(String prefix, Iterable iterable) {
+ prettyPrint(", ", prefix, ".", iterable);
+ }
+ private static void prettyPrint(String prefix, String suffix, Iterable iterable) {
+ prettyPrint(", ", prefix, suffix, iterable);
+ }
+
+ private static void prettyPrint(String delimiter, String prefix, String suffix, Iterable iterable) {
+ StringJoiner joiner = new StringJoiner(delimiter, prefix, ".");
+ Iterator iterator = iterable.iterator();
+ while (iterator.hasNext()) {
+ joiner.add(iterator.next().toString());
+ }
+
+ System.out.println(joiner);
+ }
+}
diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java
new file mode 100644
index 000000000..edb9275c1
--- /dev/null
+++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java
@@ -0,0 +1,192 @@
+package com.iluwatar.fluentinterface.fluentiterable;
+
+import java.util.*;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+/**
+ * The FluentIterable is a more convenient implementation of the common iterable interface based
+ * on the fluent interface design pattern.
+ * This implementation demonstrates a possible way to implement this functionality, but
+ * doesn't aim to be complete. It was inspired by Guava's com.google.common.collect.FluentIterable.
+ * @param is the class of objects the iterable contains
+ */
+public class FluentIterable implements Iterable {
+
+ private final Iterable iterable;
+
+ /**
+ * This constructor creates a copy of a given iterable's contents.
+ * @param iterable the iterable this interface copies to work on.
+ */
+ protected FluentIterable(Iterable iterable) {
+ ArrayList copy = new ArrayList<>();
+ Iterator iterator = iterable.iterator();
+ while (iterator.hasNext()) {
+ copy.add(iterator.next());
+ }
+ this.iterable = copy;
+ }
+
+ /**
+ * Iterates over all elements of this iterator and filters them.
+ * @param predicate the condition to test with for the filtering. If the test
+ * is negative, the tested object is removed by the iterator.
+ * @return the same FluentIterable with a filtered collection
+ */
+ public final FluentIterable filter(Predicate super TYPE> predicate) {
+ Iterator iterator = iterator();
+ while (iterator.hasNext()) {
+ TYPE nextElement = iterator.next();
+ if(!predicate.test(nextElement)) {
+ iterator.remove();
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Uses the Iterable interface's forEach method to apply a given function
+ * for each object of the iterator.
+ * @param action the action for each object
+ * @return the same FluentIterable with an untouched collection
+ */
+ public final FluentIterable forEachDo(Consumer super TYPE> action) {
+ iterable.forEach(action);
+ return this;
+ }
+
+ /**
+ * Can be used to collect objects from the iteration.
+ * @return an option of the first object of the iteration
+ */
+ public final Optional first() {
+ List list = first(1).asList();
+ if(list.isEmpty()) {
+ return Optional.empty();
+ }
+ return Optional.of(list.get(0));
+ }
+
+ /**
+ * Can be used to collect objects from the iteration.
+ * @param count defines the number of objects to return
+ * @return the same FluentIterable with a collection decimated to a maximum of 'count' first objects.
+ */
+ public final FluentIterable first(int count) {
+ Iterator iterator = iterator();
+ int currentCount = 0;
+ while (iterator.hasNext()) {
+ iterator.next();
+ if(currentCount >= count) {
+ iterator.remove();
+ }
+ currentCount++;
+ }
+ return this;
+ }
+
+ /**
+ * Can be used to collect objects from the iteration.
+ * @return an option of the last object of the iteration
+ */
+ public final Optional last() {
+ List list = last(1).asList();
+ if(list.isEmpty()) {
+ return Optional.empty();
+ }
+ return Optional.of(list.get(0));
+ }
+
+ /**
+ * Can be used to collect objects from the iteration.
+ * @param count defines the number of objects to return
+ * @return the same FluentIterable with a collection decimated to a maximum of 'count' last objects
+ */
+ public final FluentIterable last(int count) {
+ int remainingElementsCount = getRemainingElementsCount();
+ Iterator iterator = iterator();
+ int currentIndex = 0;
+ while (iterator.hasNext()) {
+ iterator.next();
+ if(currentIndex < remainingElementsCount - count) {
+ iterator.remove();
+ }
+ currentIndex++;
+ }
+
+ return this;
+ }
+
+ /**
+ * Transforms this FluentIterable into a new one containing objects of the type NEW_TYPE.
+ * @param function a function that transforms an instance of TYPE into an instance of NEW_TYPE
+ * @param the target type of the transformation
+ * @return a new FluentIterable of the new type
+ */
+ public final FluentIterable map(Function super TYPE, NEW_TYPE> function) {
+ List temporaryList = new ArrayList();
+ Iterator iterator = iterator();
+ while (iterator.hasNext()) {
+ temporaryList.add(function.apply(iterator.next()));
+ }
+ return from(temporaryList);
+ }
+
+ /**
+ * Collects all remaining objects of this iteration into a list.
+ * @return a list with all remaining objects of this iteration
+ */
+ public List asList() {
+ return toList(iterable.iterator());
+ }
+
+ /**
+ * @return a FluentIterable from a given iterable. Calls the FluentIterable constructor.
+ */
+ public static final FluentIterable from(Iterable iterable) {
+ return new FluentIterable<>(iterable);
+ }
+
+ @Override
+ public Iterator iterator() {
+ return iterable.iterator();
+ }
+
+ @Override
+ public void forEach(Consumer super TYPE> action) {
+ iterable.forEach(action);
+ }
+
+
+ @Override
+ public Spliterator spliterator() {
+ return iterable.spliterator();
+ }
+
+ /**
+ * @return the count of remaining objects in the current iteration
+ */
+ public final int getRemainingElementsCount() {
+ int counter = 0;
+ Iterator iterator = iterator();
+ while(iterator.hasNext()) {
+ iterator.next();
+ counter++;
+ }
+ return counter;
+ }
+
+ /**
+ * Collects the remaining objects of the given iterators iteration into an List.
+ * @return a new List with the remaining objects.
+ */
+ public static List toList(Iterator iterator) {
+ List copy = new ArrayList<>();
+ while (iterator.hasNext()) {
+ copy.add(iterator.next());
+ }
+ return copy;
+ }
+}
diff --git a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/AppTest.java b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/AppTest.java
new file mode 100644
index 000000000..32bbca430
--- /dev/null
+++ b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/AppTest.java
@@ -0,0 +1,12 @@
+package com.iluwatar.fluentinterface;
+
+import org.junit.Test;
+
+public class AppTest {
+
+ @Test
+ public void test() {
+ String[] args = {};
+ App.main(args);
+ }
+}
diff --git a/pom.xml b/pom.xml
index 7b0d80bd8..2c040005b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -77,7 +77,8 @@
step-builder
layers
message-channel
-
+ fluentinterface
+