SHOW:
|
|
- or go back to the newest paste.
1 | public interface OptionalMapper<T, R> { | |
2 | Optional<R> optionalMap(T t); | |
3 | } | |
4 | ||
5 | public class OptionalMapOp<T, R> implements IntermediateOp<T, R> { | |
6 | public final OptionalMapper<? super T, ? extends R> mapper; | |
7 | ||
8 | public OptionalMapOp(OptionalMapper<? super T, ? extends R> mapper) { | |
9 | this.mapper = Objects.requireNonNull(mapper); | |
10 | } | |
11 | ||
12 | @Override | |
13 | public int getOpFlags() { | |
14 | - | return 1; // TODO |
14 | + | return StreamOpFlags.NOT_SORTED | StreamOpFlags.NOT_DISTINCT; |
15 | - | //return StreamOpFlags.NOT_SORTED | StreamOpFlags.NOT_DISTINCT; |
15 | + | |
16 | ||
17 | @Override | |
18 | public Iterator<R> wrapIterator(int flags, final Iterator<T> source) { | |
19 | return iterator(source, mapper); | |
20 | } | |
21 | ||
22 | @Override | |
23 | public Sink<T> wrapSink(int flags, Sink sink) { | |
24 | return new Sink.ChainedValue<T>(sink) { | |
25 | @Override | |
26 | public void accept(T t) { | |
27 | for (R r : Optionals.toIterable(mapper.optionalMap(t))) { | |
28 | downstream.accept(r); | |
29 | } | |
30 | } | |
31 | }; | |
32 | } | |
33 | ||
34 | public static<T, R> Iterator<R> iterator(final Iterator<T> source, final OptionalMapper<? super T, ? extends R> mapper) { | |
35 | Objects.requireNonNull(source); | |
36 | Objects.requireNonNull(mapper); | |
37 | ||
38 | return new OptionalMapIterator(source, mapper); | |
39 | } | |
40 | ||
41 | static class OptionalMapIterator<T, R> implements Iterator<R> { | |
42 | final Iterator<T> source; | |
43 | final OptionalMapper<? super T, ? extends R> mapper; | |
44 | ||
45 | boolean haveNext = false; | |
46 | Optional<? extends R> nextValue = Optional.<R>empty(); | |
47 | ||
48 | OptionalMapIterator(final Iterator<T> source, final OptionalMapper<? super T, ? extends R> mapper) { | |
49 | this.source = source; | |
50 | this.mapper = mapper; | |
51 | } | |
52 | ||
53 | public void tryToGetNext() { | |
54 | if (!haveNext) { | |
55 | while (source.hasNext()) { | |
56 | final T sourceNext = source.next(); | |
57 | nextValue = mapper.optionalMap(sourceNext); | |
58 | ||
59 | if (nextValue.isPresent()) { | |
60 | haveNext = true; | |
61 | return; | |
62 | } | |
63 | } | |
64 | } | |
65 | } | |
66 | ||
67 | @Override | |
68 | public boolean hasNext() { | |
69 | tryToGetNext(); | |
70 | return haveNext; | |
71 | } | |
72 | ||
73 | @Override | |
74 | public R next() { | |
75 | tryToGetNext(); | |
76 | ||
77 | if (haveNext) { | |
78 | final Optional<? extends R> result = nextValue; | |
79 | haveNext = false; | |
80 | nextValue = Optional.<R>empty(); | |
81 | return result.get(); | |
82 | } else { | |
83 | throw new NoSuchElementException(); | |
84 | } | |
85 | } | |
86 | } | |
87 | } | |
88 | ||
89 | public class MoreStreams { | |
90 | // This is a quick and dirty example that works. | |
91 | // The cast and the generic types would have to be fixed for a non-throwaway implementation. | |
92 | public static <T, R> Stream<R> optionalMap(Stream<T> stream, OptionalMapper<? super T, R> mapper) { | |
93 | final ValuePipeline vp = (ValuePipeline) stream; | |
94 | final OptionalMapOp mapOp = new OptionalMapOp<>(mapper); | |
95 | return chainValue(vp, mapOp); | |
96 | } | |
97 | ||
98 | protected static <E_IN, E_OUT> Stream<E_OUT> chainValue(AbstractPipeline<E_IN, E_OUT> pipeline, IntermediateOp<E_OUT, E_OUT> op) { | |
99 | return new ValuePipeline<>(pipeline, op); | |
100 | } | |
101 | } | |
102 | ||
103 | public class ZipCodeTest { | |
104 | public static class Address { | |
105 | public final Optional<String> zipOption; | |
106 | public Address(Optional<String> zipOption) { this.zipOption = zipOption; } | |
107 | } | |
108 | public static class Person { | |
109 | public final Optional<Address> addressOption; | |
110 | public Person(Optional<Address> addressOption) { this.addressOption = addressOption; } | |
111 | } | |
112 | ||
113 | public static void main(String[] args) { | |
114 | List<Person> people = new ArrayList<Person>(); | |
115 | people.add(new Person(Optional.<Address>empty())); | |
116 | people.add(new Person(new Optional(new Address(Optional.<String>empty())))); | |
117 | people.add(new Person(new Optional(new Address(new Optional("12345"))))); | |
118 | people.add(new Person(new Optional(new Address(Optional.<String>empty())))); | |
119 | people.add(new Person(new Optional(new Address(new Optional("45678"))))); | |
120 | people.add(new Person(new Optional(new Address(new Optional("98765"))))); | |
121 | people.add(new Person(Optional.<Address>empty())); | |
122 | ||
123 | Stream<Person> s = people.stream(); | |
124 | ValuePipeline vp = (ValuePipeline) s; | |
125 | ||
126 | // -------------------------------------------------------- | |
127 | // Regular map example: JDK8 supports this... | |
128 | ||
129 | final List<Optional<Address>> optAddresses = new ArrayList<Optional<Address>>(); | |
130 | // Using static function syntax to match later examples: | |
131 | MoreStreams.map(people.stream(), (p) -> p.addressOption).into(optAddresses); | |
132 | // Nicer Syntax is built into JDK: | |
133 | people.stream().map((p) -> p.addressOption).into(optAddresses); | |
134 | ||
135 | // -------------------------------------------------------- | |
136 | // optionalMap(flatMap) example: JDK8 purposefully omits... | |
137 | ||
138 | final List<Address> addresses = new ArrayList<Address>(); | |
139 | optionalMap(people.stream(), (p) -> p.addressOption).into(addresses); | |
140 | // If JDK8 had this built-in, the nicer syntax would be : | |
141 | //people.stream().optionalMap((p) -> p.addressOption).into(addresses); | |
142 | ||
143 | final List<String> zips = new ArrayList<String>(); | |
144 | optionalMap(optionalMap(people.stream(), (p) -> p.addressOption), (a) -> a.zipOption).into(zips); | |
145 | // If JDK8 had this built-in, the nicer syntax would be : | |
146 | //people.stream().optionalMap((p) -> p.addressOption).optionalMap((a) -> a.zipOption).into(zips); | |
147 | } | |
148 | } |