|
1 | 1 | package com.iluwatar.fluentinterface.fluentiterable; |
2 | 2 |
|
3 | | -import java.util.*; |
| 3 | +import java.util.ArrayList; |
| 4 | +import java.util.Iterator; |
| 5 | +import java.util.List; |
| 6 | +import java.util.Optional; |
4 | 7 | import java.util.function.Consumer; |
5 | 8 | import java.util.function.Function; |
6 | 9 | import java.util.function.Predicate; |
7 | 10 |
|
8 | 11 | /** |
9 | 12 | * The FluentIterable is a more convenient implementation of the common iterable interface based |
10 | 13 | * on the fluent interface design pattern. |
11 | | - * This implementation demonstrates a possible way to implement this functionality, but |
| 14 | + * This interface defines common operations, but |
12 | 15 | * doesn't aim to be complete. It was inspired by Guava's com.google.common.collect.FluentIterable. |
13 | 16 | * @param <TYPE> is the class of objects the iterable contains |
14 | 17 | */ |
15 | | -public class FluentIterable<TYPE> implements Iterable<TYPE> { |
16 | | - |
17 | | - private final Iterable<TYPE> iterable; |
| 18 | +public interface FluentIterable<TYPE> extends Iterable<TYPE> { |
18 | 19 |
|
19 | 20 | /** |
20 | | - * This constructor creates a copy of a given iterable's contents. |
21 | | - * @param iterable the iterable this interface copies to work on. |
22 | | - */ |
23 | | - protected FluentIterable(Iterable<TYPE> iterable) { |
24 | | - ArrayList<TYPE> copy = new ArrayList<>(); |
25 | | - Iterator<TYPE> iterator = iterable.iterator(); |
26 | | - while (iterator.hasNext()) { |
27 | | - copy.add(iterator.next()); |
28 | | - } |
29 | | - this.iterable = copy; |
30 | | - } |
31 | | - |
32 | | - /** |
33 | | - * Iterates over all elements of this iterator and filters them. |
| 21 | + * Filters the iteration with the given predicate. |
34 | 22 | * @param predicate the condition to test with for the filtering. If the test |
35 | 23 | * is negative, the tested object is removed by the iterator. |
36 | | - * @return the same FluentIterable with a filtered collection |
| 24 | + * @return a filtered FluentIterable |
37 | 25 | */ |
38 | | - public final FluentIterable<TYPE> filter(Predicate<? super TYPE> predicate) { |
39 | | - Iterator<TYPE> iterator = iterator(); |
40 | | - while (iterator.hasNext()) { |
41 | | - TYPE nextElement = iterator.next(); |
42 | | - if(!predicate.test(nextElement)) { |
43 | | - iterator.remove(); |
44 | | - } |
45 | | - } |
46 | | - return this; |
47 | | - } |
| 26 | + FluentIterable<TYPE> filter(Predicate<? super TYPE> predicate); |
48 | 27 |
|
49 | 28 | /** |
50 | 29 | * Uses the Iterable interface's forEach method to apply a given function |
51 | | - * for each object of the iterator. |
52 | | - * @param action the action for each object |
53 | | - * @return the same FluentIterable with an untouched collection |
| 30 | + * for each object of the iterator. This is a terminating operation. |
54 | 31 | */ |
55 | | - public final FluentIterable<TYPE> forEachDo(Consumer<? super TYPE> action) { |
56 | | - iterable.forEach(action); |
57 | | - return this; |
58 | | - } |
| 32 | + void forEachDo(Consumer<? super TYPE> action); |
59 | 33 |
|
60 | 34 | /** |
61 | | - * Can be used to collect objects from the iteration. |
62 | | - * @return an option of the first object of the iteration |
| 35 | + * Evaluates the iteration and returns the first element. This is a terminating operation. |
| 36 | + * @return the first element after the iteration is evaluated |
63 | 37 | */ |
64 | | - public final Optional<TYPE> first() { |
65 | | - List<TYPE> list = first(1).asList(); |
66 | | - if(list.isEmpty()) { |
67 | | - return Optional.empty(); |
68 | | - } |
69 | | - return Optional.of(list.get(0)); |
70 | | - } |
| 38 | + Optional<TYPE> first(); |
71 | 39 |
|
72 | 40 | /** |
73 | | - * Can be used to collect objects from the iteration. |
74 | | - * @param count defines the number of objects to return |
75 | | - * @return the same FluentIterable with a collection decimated to a maximum of 'count' first objects. |
| 41 | + * Evaluates the iteration and leaves only the count first elements. |
| 42 | + * @return the first count elements as an Iterable |
76 | 43 | */ |
77 | | - public final FluentIterable<TYPE> first(int count) { |
78 | | - Iterator<TYPE> iterator = iterator(); |
79 | | - int currentCount = 0; |
80 | | - while (iterator.hasNext()) { |
81 | | - iterator.next(); |
82 | | - if(currentCount >= count) { |
83 | | - iterator.remove(); |
84 | | - } |
85 | | - currentCount++; |
86 | | - } |
87 | | - return this; |
88 | | - } |
| 44 | + FluentIterable<TYPE> first(int count); |
89 | 45 |
|
90 | 46 | /** |
91 | | - * Can be used to collect objects from the iteration. |
92 | | - * @return an option of the last object of the iteration |
| 47 | + * Evaluates the iteration and returns the last element. This is a terminating operation. |
| 48 | + * @return the last element after the iteration is evaluated |
93 | 49 | */ |
94 | | - public final Optional<TYPE> last() { |
95 | | - List<TYPE> list = last(1).asList(); |
96 | | - if(list.isEmpty()) { |
97 | | - return Optional.empty(); |
98 | | - } |
99 | | - return Optional.of(list.get(0)); |
100 | | - } |
| 50 | + Optional<TYPE> last(); |
101 | 51 |
|
102 | 52 | /** |
103 | | - * Can be used to collect objects from the iteration. |
104 | | - * @param count defines the number of objects to return |
105 | | - * @return the same FluentIterable with a collection decimated to a maximum of 'count' last objects |
| 53 | + * Evaluates the iteration and leaves only the count last elements. |
| 54 | + * @return the last counts elements as an Iterable |
106 | 55 | */ |
107 | | - public final FluentIterable<TYPE> last(int count) { |
108 | | - int remainingElementsCount = getRemainingElementsCount(); |
109 | | - Iterator<TYPE> iterator = iterator(); |
110 | | - int currentIndex = 0; |
111 | | - while (iterator.hasNext()) { |
112 | | - iterator.next(); |
113 | | - if(currentIndex < remainingElementsCount - count) { |
114 | | - iterator.remove(); |
115 | | - } |
116 | | - currentIndex++; |
117 | | - } |
118 | | - |
119 | | - return this; |
120 | | - } |
| 56 | + FluentIterable<TYPE> last(int count); |
121 | 57 |
|
122 | 58 | /** |
123 | 59 | * Transforms this FluentIterable into a new one containing objects of the type NEW_TYPE. |
124 | 60 | * @param function a function that transforms an instance of TYPE into an instance of NEW_TYPE |
125 | 61 | * @param <NEW_TYPE> the target type of the transformation |
126 | 62 | * @return a new FluentIterable of the new type |
127 | 63 | */ |
128 | | - public final <NEW_TYPE> FluentIterable<NEW_TYPE> map(Function<? super TYPE, NEW_TYPE> function) { |
129 | | - List<NEW_TYPE> temporaryList = new ArrayList(); |
130 | | - Iterator<TYPE> iterator = iterator(); |
131 | | - while (iterator.hasNext()) { |
132 | | - temporaryList.add(function.apply(iterator.next())); |
133 | | - } |
134 | | - return from(temporaryList); |
135 | | - } |
136 | | - |
137 | | - /** |
138 | | - * Collects all remaining objects of this iteration into a list. |
139 | | - * @return a list with all remaining objects of this iteration |
140 | | - */ |
141 | | - public List<TYPE> asList() { |
142 | | - return toList(iterable.iterator()); |
143 | | - } |
| 64 | + <NEW_TYPE> FluentIterable<NEW_TYPE> map(Function<? super TYPE, NEW_TYPE> function); |
| 65 | + List<TYPE> asList(); |
144 | 66 |
|
145 | 67 | /** |
146 | | - * @return a FluentIterable from a given iterable. Calls the FluentIterable constructor. |
| 68 | + * Utility method that iterates over iterable and adds the contents to a list. |
| 69 | + * @param iterable the iterable to collect |
| 70 | + * @param <TYPE> the type of the objects to iterate |
| 71 | + * @return a list with all objects of the given iterator |
147 | 72 | */ |
148 | | - public static final <TYPE> FluentIterable<TYPE> from(Iterable<TYPE> iterable) { |
149 | | - return new FluentIterable<>(iterable); |
150 | | - } |
151 | | - |
152 | | - @Override |
153 | | - public Iterator<TYPE> iterator() { |
154 | | - return iterable.iterator(); |
155 | | - } |
156 | | - |
157 | | - @Override |
158 | | - public void forEach(Consumer<? super TYPE> action) { |
159 | | - iterable.forEach(action); |
160 | | - } |
161 | | - |
162 | | - |
163 | | - @Override |
164 | | - public Spliterator<TYPE> spliterator() { |
165 | | - return iterable.spliterator(); |
166 | | - } |
167 | | - |
168 | | - /** |
169 | | - * @return the count of remaining objects in the current iteration |
170 | | - */ |
171 | | - public final int getRemainingElementsCount() { |
172 | | - int counter = 0; |
173 | | - Iterator<TYPE> iterator = iterator(); |
174 | | - while(iterator.hasNext()) { |
175 | | - iterator.next(); |
176 | | - counter++; |
177 | | - } |
178 | | - return counter; |
179 | | - } |
180 | | - |
181 | | - /** |
182 | | - * Collects the remaining objects of the given iterators iteration into an List. |
183 | | - * @return a new List with the remaining objects. |
184 | | - */ |
185 | | - public static <TYPE> List<TYPE> toList(Iterator<TYPE> iterator) { |
186 | | - List<TYPE> copy = new ArrayList<>(); |
| 73 | + static <TYPE> List<TYPE> copyToList(Iterable<TYPE> iterable) { |
| 74 | + ArrayList<TYPE> copy = new ArrayList<>(); |
| 75 | + Iterator<TYPE> iterator = iterable.iterator(); |
187 | 76 | while (iterator.hasNext()) { |
188 | 77 | copy.add(iterator.next()); |
189 | 78 | } |
|
0 commit comments