diff --git a/faq.md b/faq.md
index 5633a693d..b98bc7589 100644
--- a/faq.md
+++ b/faq.md
@@ -61,3 +61,7 @@ As for performance and scalability, pools can become bottlenecks, if all the
pooled objects are in use and more clients need them, threads will become
blocked waiting for available object from the pool. This is not the case with
Flyweight.
+
+### Q7: What are the differences between FluentInterface and Builder patterns? {#Q7}
+
+Fluent interfaces are sometimes confused with the Builder pattern, because they share method chaining and a fluent usage. However, fluent interfaces are not primarily used to create shared (mutable) objects, but to configure complex objects without having to respecify the target object on every property change.
\ No newline at end of file
diff --git a/fluentinterface/etc/fluentinterface.png b/fluentinterface/etc/fluentinterface.png
new file mode 100644
index 000000000..4a79ce0b7
Binary files /dev/null and b/fluentinterface/etc/fluentinterface.png differ
diff --git a/fluentinterface/etc/fluentinterface.ucls b/fluentinterface/etc/fluentinterface.ucls
new file mode 100644
index 000000000..3277148cd
--- /dev/null
+++ b/fluentinterface/etc/fluentinterface.ucls
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fluentinterface/index.md b/fluentinterface/index.md
new file mode 100644
index 000000000..942867933
--- /dev/null
+++ b/fluentinterface/index.md
@@ -0,0 +1,28 @@
+---
+layout: pattern
+title: Fluent Interface
+folder: fluentinterface
+permalink: /patterns/fluentinterface/
+categories: Architectural
+tags: Java
+---
+
+**Intent:** A fluent interface provides an easy-readable, flowing interface, that often mimics a domain specific language. Using this pattern results in code that can be read nearly as human language.
+
+
+
+**Applicability:** Use the Fluent Interface pattern when
+
+* you provide an API that would benefit from a DSL-like usage
+* you have objects that are difficult to configure or use
+
+**Real world examples:**
+
+* [Java 8 Stream API](http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html)
+* [Google Guava FluentInterable](https://github.com/google/guava/wiki/FunctionalExplained)
+* [JOOQ](http://www.jooq.org/doc/3.0/manual/getting-started/use-cases/jooq-as-a-standalone-sql-builder/)
+
+**Credits**
+
+* [Fluent Interface - Martin Fowler](http://www.martinfowler.com/bliki/FluentInterface.html)
+* [Evolutionary architecture and emergent design: Fluent interfaces - Neal Ford](http://www.ibm.com/developerworks/library/j-eaed14/)
\ No newline at end of file
diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml
index c78c182e3..be8ab8039 100644
--- a/fluentinterface/pom.xml
+++ b/fluentinterface/pom.xml
@@ -5,7 +5,7 @@
java-design-patterns
com.iluwatar
- 1.5.0
+ 1.6.0
4.0.0
diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/App.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/App.java
index 96a2db323..b9e5909f1 100644
--- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/App.java
+++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/App.java
@@ -1,5 +1,6 @@
package com.iluwatar.fluentinterface;
+import com.iluwatar.fluentinterface.fluentiterable.FluentIterable;
import com.iluwatar.fluentinterface.fluentiterable.lazy.LazyFluentIterable;
import com.iluwatar.fluentinterface.fluentiterable.simple.SimpleFluentIterable;
@@ -9,96 +10,113 @@ import java.util.function.Predicate;
import static java.lang.String.valueOf;
+/**
+ * Fluent interface pattern is useful when you want to provide an easy readable, flowing API. Those
+ * interfaces tend to mimic domain specific languages, so they can nearly be read as human
+ * languages.
+ *
+ * In this example two implementations of a {@link FluentIterable} interface are given. The
+ * SimpleFluentIterable evaluates eagerly and would be too costly for real world applications. The
+ * LazyFluentIterable is evaluated on termination. Their usage is demonstrated with a simple number
+ * list that is filtered, transformed and collected. The result is printed afterwards.
+ *
+ */
public class App {
- public static void main(String[] args) {
+ 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 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 = SimpleFluentIterable.from(integerList)
- .filter(negatives())
- .first(3)
- .asList();
- prettyPrint("The first three negative values are: ", firstFiveNegatives);
+ List firstFiveNegatives =
+ SimpleFluentIterable.fromCopyOf(integerList).filter(negatives()).first(3).asList();
+ prettyPrint("The first three negative values are: ", firstFiveNegatives);
- List lastTwoPositives = SimpleFluentIterable.from(integerList)
- .filter(positives())
- .last(2)
- .asList();
- prettyPrint("The last two positive values are: ", lastTwoPositives);
+ List lastTwoPositives =
+ SimpleFluentIterable.fromCopyOf(integerList).filter(positives()).last(2).asList();
+ prettyPrint("The last two positive values are: ", lastTwoPositives);
- SimpleFluentIterable.from(integerList)
- .filter(number -> number%2 == 0)
- .first()
- .ifPresent(evenNumber -> System.out.println(String.format("The first even number is: %d", evenNumber)));
+ SimpleFluentIterable
+ .fromCopyOf(integerList)
+ .filter(number -> number % 2 == 0)
+ .first()
+ .ifPresent(
+ evenNumber -> System.out.println(String.format("The first even number is: %d",
+ evenNumber)));
- List transformedList = SimpleFluentIterable.from(integerList)
- .filter(negatives())
- .map(transformToString())
- .asList();
- prettyPrint("A string-mapped list of negative numbers contains: ", transformedList);
+ List transformedList =
+ SimpleFluentIterable.fromCopyOf(integerList).filter(negatives()).map(transformToString())
+ .asList();
+ prettyPrint("A string-mapped list of negative numbers contains: ", transformedList);
- List lastTwoOfFirstFourStringMapped = LazyFluentIterable.from(integerList)
- .filter(positives())
- .first(4)
- .last(2)
- .map(number -> "String[" + String.valueOf(number) + "]")
- .asList();
- prettyPrint("The lazy list contains the last two of the first four positive numbers mapped to Strings: ", lastTwoOfFirstFourStringMapped);
+ List lastTwoOfFirstFourStringMapped =
+ LazyFluentIterable.from(integerList).filter(positives()).first(4).last(2)
+ .map(number -> "String[" + String.valueOf(number) + "]").asList();
+ prettyPrint(
+ "The lazy list contains the last two of the first four positive numbers mapped to Strings: ",
+ lastTwoOfFirstFourStringMapped);
- LazyFluentIterable.from(integerList)
- .filter(negatives())
- .first(2)
- .last()
- .ifPresent(lastOfFirstTwo -> System.out.println(String.format("The last of the first two negatives is: %d", lastOfFirstTwo)));
+ LazyFluentIterable
+ .from(integerList)
+ .filter(negatives())
+ .first(2)
+ .last()
+ .ifPresent(
+ lastOfFirstTwo -> System.out.println(String.format(
+ "The last of the first two negatives is: %d", lastOfFirstTwo)));
+ }
+
+ private static Function transformToString() {
+ return integer -> "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());
}
- private static Function transformToString() {
- return integer -> "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);
- }
+ 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
index 919cf5664..5c4df0391 100644
--- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java
+++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java
@@ -8,73 +8,82 @@ 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 interface defines common operations, but
- * doesn't aim to be complete. It was inspired by Guava's com.google.common.collect.FluentIterable.
+ * The FluentIterable is a more convenient implementation of the common iterable interface based on
+ * the fluent interface design pattern. This interface defines common operations, 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 interface FluentIterable extends Iterable {
- /**
- * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy the predicate.
- * @param predicate the condition to test with for the filtering. If the test
- * is negative, the tested object is removed by the iterator.
- * @return a filtered FluentIterable
- */
- FluentIterable filter(Predicate super TYPE> predicate);
+ /**
+ * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy
+ * the predicate.
+ *
+ * @param predicate the condition to test with for the filtering. If the test is negative, the
+ * tested object is removed by the iterator.
+ * @return a filtered FluentIterable
+ */
+ FluentIterable filter(Predicate super TYPE> predicate);
- /**
- * Returns an Optional containing the first element of this iterable if present,
- * else returns Optional.empty().
- * @return the first element after the iteration is evaluated
- */
- Optional first();
+ /**
+ * Returns an Optional containing the first element of this iterable if present, else returns
+ * Optional.empty().
+ *
+ * @return the first element after the iteration is evaluated
+ */
+ Optional first();
- /**
- * Evaluates the iteration and leaves only the count first elements.
- * @return the first count elements as an Iterable
- */
- FluentIterable first(int count);
+ /**
+ * Evaluates the iteration and leaves only the count first elements.
+ *
+ * @return the first count elements as an Iterable
+ */
+ FluentIterable first(int count);
- /**
- * Evaluates the iteration and returns the last element. This is a terminating operation.
- * @return the last element after the iteration is evaluated
- */
- Optional last();
+ /**
+ * Evaluates the iteration and returns the last element. This is a terminating operation.
+ *
+ * @return the last element after the iteration is evaluated
+ */
+ Optional last();
- /**
- * Evaluates the iteration and leaves only the count last elements.
- * @return the last counts elements as an Iterable
- */
- FluentIterable last(int count);
+ /**
+ * Evaluates the iteration and leaves only the count last elements.
+ *
+ * @return the last counts elements as an Iterable
+ */
+ FluentIterable last(int count);
- /**
- * 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
- */
- FluentIterable map(Function super TYPE, NEW_TYPE> function);
+ /**
+ * 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
+ */
+ FluentIterable map(Function super TYPE, NEW_TYPE> function);
- /**
- * Returns the contents of this Iterable as a List.
- * @return a List representation of this Iterable
- */
- List asList();
+ /**
+ * Returns the contents of this Iterable as a List.
+ *
+ * @return a List representation of this Iterable
+ */
+ List asList();
- /**
- * Utility method that iterates over iterable and adds the contents to a list.
- * @param iterable the iterable to collect
- * @param the type of the objects to iterate
- * @return a list with all objects of the given iterator
- */
- static List copyToList(Iterable iterable) {
- ArrayList copy = new ArrayList<>();
- Iterator iterator = iterable.iterator();
- while (iterator.hasNext()) {
- copy.add(iterator.next());
- }
- return copy;
+ /**
+ * Utility method that iterates over iterable and adds the contents to a list.
+ *
+ * @param iterable the iterable to collect
+ * @param the type of the objects to iterate
+ * @return a list with all objects of the given iterator
+ */
+ static List copyToList(Iterable iterable) {
+ ArrayList copy = new ArrayList<>();
+ Iterator iterator = iterable.iterator();
+ while (iterator.hasNext()) {
+ copy.add(iterator.next());
}
+ return copy;
+ }
}
diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java
index 3c1230bce..e80356d8e 100644
--- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java
+++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java
@@ -3,53 +3,58 @@ package com.iluwatar.fluentinterface.fluentiterable.lazy;
import java.util.Iterator;
/**
- * This class is used to realize LazyFluentIterables. It decorates
- * a given iterator. Does not support consecutive hasNext() calls.
+ * This class is used to realize LazyFluentIterables. It decorates a given iterator. Does not
+ * support consecutive hasNext() calls.
+ *
* @param
*/
public abstract class DecoratingIterator implements Iterator {
- protected final Iterator fromIterator;
+ protected final Iterator fromIterator;
- private TYPE next = null;
+ private TYPE next = null;
- /**
- * Creates an iterator that decorates the given iterator.
- * @param fromIterator
- */
- public DecoratingIterator(Iterator fromIterator) {
- this.fromIterator = fromIterator;
+ /**
+ * Creates an iterator that decorates the given iterator.
+ *
+ * @param fromIterator
+ */
+ public DecoratingIterator(Iterator fromIterator) {
+ this.fromIterator = fromIterator;
+ }
+
+ /**
+ * Precomputes and saves the next element of the Iterable. null is considered as end of data.
+ *
+ * @return true if a next element is available
+ */
+ @Override
+ public final boolean hasNext() {
+ next = computeNext();
+ return next != null;
+ }
+
+ /**
+ * Returns the next element of the Iterable.
+ *
+ * @return the next element of the Iterable, or null if not present.
+ */
+ @Override
+ public final TYPE next() {
+ if (next == null) {
+ return fromIterator.next();
+ } else {
+ final TYPE result = next;
+ next = null;
+ return result;
}
+ }
- /**
- * Precomputes and saves the next element of the Iterable. null is considered as end of data.
- * @return true if a next element is available
- */
- @Override
- public final boolean hasNext() {
- next = computeNext();
- return next != null;
- }
-
- /**
- * Returns the next element of the Iterable.
- * @return the next element of the Iterable, or null if not present.
- */
- @Override
- public final TYPE next() {
- if (next == null) {
- return fromIterator.next();
- } else {
- final TYPE result = next;
- next = null;
- return result;
- }
- }
-
- /**
- * Computes the next object of the Iterable. Can be implemented to
- * realize custom behaviour for an iteration process. null is considered as end of data.
- * @return the next element of the Iterable.
- */
- public abstract TYPE computeNext();
+ /**
+ * Computes the next object of the Iterable. Can be implemented to realize custom behaviour for an
+ * iteration process. null is considered as end of data.
+ *
+ * @return the next element of the Iterable.
+ */
+ public abstract TYPE computeNext();
}
diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java
index 998bbd659..5adfa83ce 100644
--- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java
+++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java
@@ -11,209 +11,221 @@ import java.util.function.Function;
import java.util.function.Predicate;
/**
- * This is a lazy implementation of the FluentIterable interface. It evaluates
- * all chained operations when a terminating operation is applied.
+ * This is a lazy implementation of the FluentIterable interface. It evaluates all chained
+ * operations when a terminating operation is applied.
+ *
* @param the type of the objects the iteration is about
*/
public class LazyFluentIterable implements FluentIterable {
- private final Iterable iterable;
+ private final Iterable iterable;
- /**
- * This constructor creates a new LazyFluentIterable. It wraps the
- * given iterable.
- * @param iterable the iterable this FluentIterable works on.
- */
- protected LazyFluentIterable(Iterable iterable) {
- this.iterable = iterable;
- }
+ /**
+ * This constructor creates a new LazyFluentIterable. It wraps the given iterable.
+ *
+ * @param iterable the iterable this FluentIterable works on.
+ */
+ protected LazyFluentIterable(Iterable iterable) {
+ this.iterable = iterable;
+ }
- /**
- * This constructor can be used to implement anonymous subclasses
- * of the LazyFluentIterable.
- */
- protected LazyFluentIterable() {
- iterable = this;
- }
+ /**
+ * This constructor can be used to implement anonymous subclasses of the LazyFluentIterable.
+ */
+ protected LazyFluentIterable() {
+ iterable = this;
+ }
- /**
- * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy the predicate.
- * @param predicate the condition to test with for the filtering. If the test
- * is negative, the tested object is removed by the iterator.
- * @return a new FluentIterable object that decorates the source iterable
- */
- @Override
- public FluentIterable filter(Predicate super TYPE> predicate) {
- return new LazyFluentIterable() {
- @Override
- public Iterator iterator() {
- return new DecoratingIterator(iterable.iterator()) {
- @Override
- public TYPE computeNext() {
- while(fromIterator.hasNext()) {
- TYPE candidate = fromIterator.next();
- if(!predicate.test(candidate)) {
- continue;
- }
- return candidate;
- }
-
- return null;
- }
- };
- }
- };
- }
-
- /**
- * Can be used to collect objects from the iteration. Is a terminating operation.
- * @return an Optional containing the first object of this Iterable
- */
- @Override
- public Optional first() {
- Iterator resultIterator = first(1).iterator();
- return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty();
- }
-
- /**
- * 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.
- */
- @Override
- public FluentIterable first(int count) {
- return new LazyFluentIterable() {
- @Override
- public Iterator iterator() {
- return new DecoratingIterator(iterable.iterator()) {
- int currentIndex = 0;
-
- @Override
- public TYPE computeNext() {
- if(currentIndex < count) {
- if(fromIterator.hasNext()) {
- TYPE candidate = fromIterator.next();
- currentIndex++;
- return candidate;
- }
- }
- return null;
- }
- };
- }
- };
- }
-
- /**
- * Can be used to collect objects from the iteration. Is a terminating operation.
- * @return an Optional containing the last object of this Iterable
- */
- @Override
- public Optional last() {
- Iterator resultIterator = last(1).iterator();
- return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty();
- }
-
- /**
- * Can be used to collect objects from the Iterable. Is a terminating operation.
- * This operation is memory intensive, because the contents of this Iterable
- * are collected into a List, when the next object is requested.
- * @param count defines the number of objects to return
- * @return the same FluentIterable with a collection decimated to a maximum of 'count' last objects
- */
- @Override
- public FluentIterable last(int count) {return new LazyFluentIterable() {
- @Override
- public Iterator iterator() {
- return new DecoratingIterator(iterable.iterator()) {
- public int stopIndex;
- public int totalElementsCount;
- private List list;
- private int currentIndex = 0;
-
- @Override
- public TYPE computeNext() {
- initialize();
-
- TYPE candidate = null;
- while(currentIndex < stopIndex && fromIterator.hasNext()) {
- currentIndex++;
- fromIterator.next();
- }
- if(currentIndex >= stopIndex && fromIterator.hasNext()) {
- candidate = fromIterator.next();
- }
- return candidate;
- }
-
- private void initialize() {
- if(list == null) {
- list = new ArrayList<>();
- Iterator newIterator = iterable.iterator();
- while(newIterator.hasNext()) {
- list.add(newIterator.next());
- }
-
- totalElementsCount = list.size();
- stopIndex = totalElementsCount - count;
- }
- }
- };
- }
- };
- }
-
- /**
- * 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
- */
- @Override
- public FluentIterable map(Function super TYPE, NEW_TYPE> function) {
- return new LazyFluentIterable() {
- @Override
- public Iterator iterator() {
- return new DecoratingIterator(null) {
- Iterator oldTypeIterator = iterable.iterator();
- @Override
- public NEW_TYPE computeNext() {
- while(oldTypeIterator.hasNext()) {
- TYPE candidate = oldTypeIterator.next();
- return function.apply(candidate);
- }
- return null;
- }
- };
- }
- };
- }
-
- /**
- * Collects all remaining objects of this iteration into a list.
- * @return a list with all remaining objects of this iteration
- */
- @Override
- public List asList() {
- List copy = FluentIterable.copyToList(iterable);
- return copy;
- }
-
- @Override
- public Iterator iterator() {
+ /**
+ * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy
+ * the predicate.
+ *
+ * @param predicate the condition to test with for the filtering. If the test is negative, the
+ * tested object is removed by the iterator.
+ * @return a new FluentIterable object that decorates the source iterable
+ */
+ @Override
+ public FluentIterable filter(Predicate super TYPE> predicate) {
+ return new LazyFluentIterable() {
+ @Override
+ public Iterator iterator() {
return new DecoratingIterator(iterable.iterator()) {
- @Override
- public TYPE computeNext() {
- return fromIterator.next();
+ @Override
+ public TYPE computeNext() {
+ while (fromIterator.hasNext()) {
+ TYPE candidate = fromIterator.next();
+ if (!predicate.test(candidate)) {
+ continue;
+ }
+ return candidate;
}
- };
- }
- /**
- * @return a FluentIterable from a given iterable. Calls the LazyFluentIterable constructor.
- */
- public static final FluentIterable from(Iterable iterable) {
- return new LazyFluentIterable<>(iterable);
- }
+ return null;
+ }
+ };
+ }
+ };
+ }
+
+ /**
+ * Can be used to collect objects from the iteration. Is a terminating operation.
+ *
+ * @return an Optional containing the first object of this Iterable
+ */
+ @Override
+ public Optional first() {
+ Iterator resultIterator = first(1).iterator();
+ return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty();
+ }
+
+ /**
+ * 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.
+ */
+ @Override
+ public FluentIterable first(int count) {
+ return new LazyFluentIterable() {
+ @Override
+ public Iterator iterator() {
+ return new DecoratingIterator(iterable.iterator()) {
+ int currentIndex = 0;
+
+ @Override
+ public TYPE computeNext() {
+ if (currentIndex < count) {
+ if (fromIterator.hasNext()) {
+ TYPE candidate = fromIterator.next();
+ currentIndex++;
+ return candidate;
+ }
+ }
+ return null;
+ }
+ };
+ }
+ };
+ }
+
+ /**
+ * Can be used to collect objects from the iteration. Is a terminating operation.
+ *
+ * @return an Optional containing the last object of this Iterable
+ */
+ @Override
+ public Optional last() {
+ Iterator resultIterator = last(1).iterator();
+ return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty();
+ }
+
+ /**
+ * Can be used to collect objects from the Iterable. Is a terminating operation. This operation is
+ * memory intensive, because the contents of this Iterable are collected into a List, when the
+ * next object is requested.
+ *
+ * @param count defines the number of objects to return
+ * @return the same FluentIterable with a collection decimated to a maximum of 'count' last
+ * objects
+ */
+ @Override
+ public FluentIterable last(int count) {
+ return new LazyFluentIterable() {
+ @Override
+ public Iterator iterator() {
+ return new DecoratingIterator(iterable.iterator()) {
+ private int stopIndex;
+ private int totalElementsCount;
+ private List list;
+ private int currentIndex = 0;
+
+ @Override
+ public TYPE computeNext() {
+ initialize();
+
+ TYPE candidate = null;
+ while (currentIndex < stopIndex && fromIterator.hasNext()) {
+ currentIndex++;
+ fromIterator.next();
+ }
+ if (currentIndex >= stopIndex && fromIterator.hasNext()) {
+ candidate = fromIterator.next();
+ }
+ return candidate;
+ }
+
+ private void initialize() {
+ if (list == null) {
+ list = new ArrayList<>();
+ Iterator newIterator = iterable.iterator();
+ while (newIterator.hasNext()) {
+ list.add(newIterator.next());
+ }
+
+ totalElementsCount = list.size();
+ stopIndex = totalElementsCount - count;
+ }
+ }
+ };
+ }
+ };
+ }
+
+ /**
+ * 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
+ */
+ @Override
+ public FluentIterable map(Function super TYPE, NEW_TYPE> function) {
+ return new LazyFluentIterable() {
+ @Override
+ public Iterator iterator() {
+ return new DecoratingIterator(null) {
+ Iterator oldTypeIterator = iterable.iterator();
+
+ @Override
+ public NEW_TYPE computeNext() {
+ while (oldTypeIterator.hasNext()) {
+ TYPE candidate = oldTypeIterator.next();
+ return function.apply(candidate);
+ }
+ return null;
+ }
+ };
+ }
+ };
+ }
+
+ /**
+ * Collects all remaining objects of this iteration into a list.
+ *
+ * @return a list with all remaining objects of this iteration
+ */
+ @Override
+ public List asList() {
+ List copy = FluentIterable.copyToList(iterable);
+ return copy;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return new DecoratingIterator(iterable.iterator()) {
+ @Override
+ public TYPE computeNext() {
+ return fromIterator.next();
+ }
+ };
+ }
+
+ /**
+ * @return a FluentIterable from a given iterable. Calls the LazyFluentIterable constructor.
+ */
+ public static final FluentIterable from(Iterable iterable) {
+ return new LazyFluentIterable<>(iterable);
+ }
}
diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java
index 0736387e5..db7a31954 100644
--- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java
+++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java
@@ -8,175 +8,191 @@ import java.util.function.Function;
import java.util.function.Predicate;
/**
- * This is a simple implementation of the FluentIterable interface. It evaluates
- * all chained operations eagerly.
- * This implementation would be costly to be utilized in real applications.
+ * This is a simple implementation of the FluentIterable interface. It evaluates all chained
+ * operations eagerly. This implementation would be costly to be utilized in real applications.
+ *
* @param the type of the objects the iteration is about
*/
public class SimpleFluentIterable implements FluentIterable {
- private final Iterable 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 SimpleFluentIterable(Iterable iterable) {
- List copy = FluentIterable.copyToList(iterable);
- this.iterable = copy;
+ /**
+ * This constructor creates a copy of a given iterable's contents.
+ *
+ * @param iterable the iterable this interface copies to work on.
+ */
+ protected SimpleFluentIterable(Iterable iterable) {
+ this.iterable = iterable;
+ }
+
+ /**
+ * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy
+ * the predicate.
+ *
+ * @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
+ */
+ @Override
+ 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;
+ }
+
+ /**
+ * Can be used to collect objects from the Iterable. Is a terminating operation.
+ *
+ * @return an option of the first object of the Iterable
+ */
+ @Override
+ public final Optional first() {
+ Iterator resultIterator = first(1).iterator();
+ return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty();
+ }
+
+ /**
+ * Can be used to collect objects from the Iterable. Is a terminating operation.
+ *
+ * @param count defines the number of objects to return
+ * @return the same FluentIterable with a collection decimated to a maximum of 'count' first
+ * objects.
+ */
+ @Override
+ 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 Iterable. Is a terminating operation.
+ *
+ * @return an option of the last object of the Iterable
+ */
+ @Override
+ 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 Iterable. Is a terminating operation.
+ *
+ * @param count defines the number of objects to return
+ * @return the same FluentIterable with a collection decimated to a maximum of 'count' last
+ * objects
+ */
+ @Override
+ 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++;
}
- /**
- * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy the predicate.
- * @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
- */
- @Override
- 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;
+ 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
+ */
+ @Override
+ 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);
+ }
- /**
- * Can be used to collect objects from the Iterable. Is a terminating operation.
- * @return an option of the first object of the Iterable
- */
- @Override
- public final Optional first() {
- Iterator resultIterator = first(1).iterator();
- return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty();
+ /**
+ * Collects all remaining objects of this Iterable into a list.
+ *
+ * @return a list with all remaining objects of this Iterable
+ */
+ @Override
+ public List asList() {
+ return toList(iterable.iterator());
+ }
+
+ /**
+ * @return a FluentIterable from a given iterable. Calls the SimpleFluentIterable constructor.
+ */
+ public static final FluentIterable from(Iterable iterable) {
+ return new SimpleFluentIterable<>(iterable);
+ }
+
+ public static final FluentIterable fromCopyOf(Iterable iterable) {
+ List copy = FluentIterable.copyToList(iterable);
+ return new SimpleFluentIterable<>(copy);
+ }
+
+ @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 of the current Iterable
+ */
+ public final int getRemainingElementsCount() {
+ int counter = 0;
+ Iterator iterator = iterator();
+ while (iterator.hasNext()) {
+ iterator.next();
+ counter++;
}
+ return counter;
+ }
- /**
- * Can be used to collect objects from the Iterable. Is a terminating operation.
- * @param count defines the number of objects to return
- * @return the same FluentIterable with a collection decimated to a maximum of 'count' first objects.
- */
- @Override
- 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 Iterable. Is a terminating operation.
- * @return an option of the last object of the Iterable
- */
- @Override
- 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 Iterable. Is a terminating operation.
- * @param count defines the number of objects to return
- * @return the same FluentIterable with a collection decimated to a maximum of 'count' last objects
- */
- @Override
- 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
- */
- @Override
- 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 Iterable into a list.
- * @return a list with all remaining objects of this Iterable
- */
- @Override
- public List asList() {
- return toList(iterable.iterator());
- }
-
- /**
- * @return a FluentIterable from a given iterable. Calls the SimpleFluentIterable constructor.
- */
- public static final FluentIterable from(Iterable iterable) {
- return new SimpleFluentIterable<>(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 of the current Iterable
- */
- 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 iterator into a 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;
+ /**
+ * Collects the remaining objects of the given iterator into a 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
index 32bbca430..d0abb7bf1 100644
--- a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/AppTest.java
+++ b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/AppTest.java
@@ -4,9 +4,9 @@ import org.junit.Test;
public class AppTest {
- @Test
- public void test() {
- String[] args = {};
- App.main(args);
- }
+ @Test
+ public void test() {
+ String[] args = {};
+ App.main(args);
+ }
}