Skip to content

Commit 52aafa3

Browse files
committed
- added skip() and last() fixes #15 (tests pending)
1 parent d8a7853 commit 52aafa3

File tree

11 files changed

+144
-54
lines changed

11 files changed

+144
-54
lines changed

src/main/java/br/com/zbra/androidlinq/AbstractStream.java

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111

1212
abstract class AbstractStream<T> implements Stream<T> {
1313

14-
protected abstract Iterator<T> reverseIterator();
14+
protected Iterator<T> reverseIterator() {
15+
Deque<T> deque = new LinkedList<>();
16+
for (T t : this) deque.addFirst(t);
17+
return deque.iterator();
18+
}
1519

1620
@Override
1721
public Stream<T> where(Predicate<T> predicate) {
@@ -75,6 +79,11 @@ public Stream<T> take(int count) {
7579
return new TakeStream<>(this, count);
7680
}
7781

82+
@Override
83+
public Stream<T> skip(int count) {
84+
return new SkipStream<>(this, count);
85+
}
86+
7887
@Override
7988
public Stream<T> distinct() {
8089
HashSet<T> set = new HashSet<>();
@@ -133,29 +142,30 @@ public int count() {
133142

134143
@Override
135144
public T first() {
136-
Iterator<T> iterator = iterator();
137-
if (iterator.hasNext())
138-
return iterator.next();
139-
return null;
145+
return iterator().next();
140146
}
141147

142148
@Override
143149
public T first(Predicate<T> predicate) {
144-
for (T entry : this) {
145-
if (predicate.apply(entry))
146-
return entry;
147-
}
148-
return null;
150+
return where(predicate).first();
151+
}
152+
153+
@Override
154+
public T last() {
155+
return reverseIterator().next();
156+
}
157+
158+
@Override
159+
public T last(Predicate<T> predicate) {
160+
return where(predicate).last();
149161
}
150162

151163
@Override
152164
public T single() throws MultipleElementsFoundException {
153-
T result = null;
154-
for (T entry : this) {
155-
if (result != null)
156-
throw new MultipleElementsFoundException();
157-
result = entry;
158-
}
165+
Iterator<T> iterator = iterator();
166+
T result = iterator.next();
167+
if (iterator.hasNext())
168+
throw new MultipleElementsFoundException();
159169
return result;
160170
}
161171

src/main/java/br/com/zbra/androidlinq/GroupByStream.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public Iterator<Grouping<TKey, TElement>> iterator() {
2424

2525
@Override
2626
protected Iterator<Grouping<TKey, TElement>> reverseIterator() {
27-
return getGroupingIterator(stream.reverseIterator());
27+
return super.reverseIterator();
2828
}
2929

3030
private Iterator<Grouping<TKey, TElement>> getGroupingIterator(Iterator<T> iterator) {

src/main/java/br/com/zbra/androidlinq/IterableStream.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,4 @@ public IterableStream(Iterable<T> iterable) {
1616
public Iterator<T> iterator() {
1717
return iterable.iterator();
1818
}
19-
20-
@Override
21-
protected Iterator<T> reverseIterator() {
22-
List<T> list = new ArrayList<>();
23-
for (T t : iterable)
24-
list.add(t);
25-
return new ListStream.ReverseListIterator<>(list);
26-
}
2719
}

src/main/java/br/com/zbra/androidlinq/ListStream.java

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.List;
55
import java.util.ListIterator;
66

7+
78
class ListStream<T> extends AbstractStream<T> {
89

910
private List<T> source;
@@ -26,19 +27,4 @@ public Iterator<T> iterator() {
2627
protected Iterator<T> reverseIterator() {
2728
return new ReverseListIterator<>(source);
2829
}
29-
30-
static class ReverseListIterator<T> implements Iterator<T> {
31-
ListIterator<T> iterator;
32-
public ReverseListIterator(List<T> list) {
33-
iterator = list.listIterator(list.size());
34-
}
35-
36-
public boolean hasNext() {
37-
return iterator.hasPrevious();
38-
}
39-
40-
public T next() {
41-
return iterator.previous();
42-
}
43-
}
4430
}

src/main/java/br/com/zbra/androidlinq/MapStream.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.Iterator;
44
import java.util.LinkedList;
55
import java.util.Map;
6+
import java.util.SortedSet;
67

78
public class MapStream<K, V> extends AbstractStream<Map.Entry<K, V>> {
89

@@ -24,7 +25,7 @@ public Iterator<Map.Entry<K, V>> iterator() {
2425

2526
@Override
2627
protected Iterator<Map.Entry<K, V>> reverseIterator() {
27-
return new LinkedList<>(map.entrySet()).descendingIterator();
28+
return iterator();
2829
}
2930

3031
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package br.com.zbra.androidlinq;
2+
3+
import java.util.Iterator;
4+
import java.util.List;
5+
import java.util.ListIterator;
6+
7+
8+
public class ReverseListIterator<T> implements Iterator<T> {
9+
ListIterator<T> iterator;
10+
public ReverseListIterator(List<T> list) {
11+
iterator = list.listIterator(list.size());
12+
}
13+
14+
public boolean hasNext() {
15+
return iterator.hasPrevious();
16+
}
17+
18+
public T next() {
19+
return iterator.previous();
20+
}
21+
}

src/main/java/br/com/zbra/androidlinq/SelectManyStream.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public Iterator<TSelected> iterator() {
2222

2323
@Override
2424
protected Iterator<TSelected> reverseIterator() {
25-
return new SelectManyIterator<>(selector, stream.reverseIterator());
25+
return super.reverseIterator();
2626
}
2727

2828
private static class SelectManyIterator<T, TSelected> implements Iterator<TSelected> {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package br.com.zbra.androidlinq;
2+
3+
import java.util.Iterator;
4+
import java.util.NoSuchElementException;
5+
6+
class SkipStream<T> extends AbstractStream<T> {
7+
8+
private final int count;
9+
private final AbstractStream<T> stream;
10+
11+
SkipStream(AbstractStream<T> stream, int count) {
12+
this.stream = stream;
13+
this.count = count;
14+
}
15+
16+
@Override
17+
public int count() {
18+
int originalCount = stream.count();
19+
return count >= originalCount ? 0 : originalCount - count;
20+
}
21+
22+
@Override
23+
public Iterator<T> iterator() {
24+
return new SkipIterator<>(stream.iterator(), count);
25+
}
26+
27+
@Override
28+
protected Iterator<T> reverseIterator() {
29+
return super.reverseIterator();
30+
}
31+
32+
private static class SkipIterator<T> implements Iterator<T> {
33+
private final long count;
34+
private final Iterator<T> wrapped;
35+
36+
public SkipIterator(Iterator<T> wrapped, long count) {
37+
this.count = count;
38+
this.wrapped = wrapped;
39+
40+
for (int i = 0; i < count && wrapped.hasNext(); i++)
41+
wrapped.next();
42+
}
43+
44+
@Override
45+
public boolean hasNext() {
46+
return wrapped.hasNext();
47+
}
48+
49+
@Override
50+
public T next() {
51+
return wrapped.next();
52+
}
53+
}
54+
}

src/main/java/br/com/zbra/androidlinq/Stream.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,14 @@ public interface Stream<T> extends Iterable<T> {
124124
*/
125125
public Stream<T> take(int count);
126126

127+
/**
128+
* Skips a specified number of contiguous elements from the start of a sequence then returns remaining elements.
129+
*
130+
* @param count The number of elements to skip.
131+
* @return An Stream of type T that contains the elements after the number of elements skipped from the start of the input sequence.
132+
*/
133+
public Stream<T> skip(int count);
134+
127135
/**
128136
* Returns distinct elements from a sequence by using the object {@code equals()} to compare values.
129137
*
@@ -219,18 +227,37 @@ public interface Stream<T> extends Iterable<T> {
219227
/**
220228
* Returns the first element of a sequence.
221229
*
222-
* @return The first element in the specified sequence or null if the sequence is empty.
230+
* @return The first element in the specified sequence.
231+
* @throws java.util.NoSuchElementException if the sequence is empty.
223232
*/
224233
public T first();
225234

226235
/**
227236
* Returns the first element in a sequence that satisfies a specified condition.
228237
*
229238
* @param predicate A function to test each element for a condition.
230-
* @return The first element in the sequence that passes the test in the specified predicate function or null if none does.
239+
* @return The first element in the sequence that passes the test in the specified predicate function.
240+
* @throws java.util.NoSuchElementException if no element matches the sequence.
231241
*/
232242
public T first(Predicate<T> predicate);
233243

244+
/**
245+
* Returns the last element of a sequence.
246+
*
247+
* @return The last element in the specified sequence.
248+
* @throws java.util.NoSuchElementException if the sequence is empty.
249+
*/
250+
public T last();
251+
252+
/**
253+
* Returns the last element in a sequence that satisfies a specified condition.
254+
*
255+
* @param predicate A function to test each element for a condition.
256+
* @return The last element in the sequence that passes the test in the specified predicate function.
257+
* @throws java.util.NoSuchElementException if no element matches the sequence.
258+
*/
259+
public T last(Predicate<T> predicate);
260+
234261
/**
235262
* Returns the only element of a sequence, or a default value if the sequence is empty; this method throws
236263
* an exception if there is more than one element in the sequence.

src/main/java/br/com/zbra/androidlinq/TakeStream.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,32 @@ class TakeStream<T> extends AbstractStream<T> {
1111
TakeStream(AbstractStream<T> stream, int count) {
1212
this.stream = stream;
1313

14-
if (count <= 0)
14+
if (count < 0)
1515
throw new IllegalArgumentException("count must be greater than 0: " + count);
1616

1717
this.count = count;
1818
}
1919

20+
@Override
21+
public int count() {
22+
return count == 0 ? 0 : Math.min(count, stream.count());
23+
}
24+
2025
@Override
2126
public Iterator<T> iterator() {
2227
return new TakeIterator<>(stream.iterator(), count);
2328
}
2429

2530
@Override
2631
protected Iterator<T> reverseIterator() {
27-
return new TakeIterator<>(stream.reverseIterator(), count);
32+
return super.reverseIterator();
2833
}
2934

3035
private static class TakeIterator<T> implements Iterator<T> {
36+
private long index = 0;
3137
private final long count;
3238
private final Iterator<T> wrapped;
3339

34-
long index = 0;
35-
3640
public TakeIterator(Iterator<T> wrapped, long count) {
3741
this.count = count;
3842
this.wrapped = wrapped;

0 commit comments

Comments
 (0)