View difference between Paste ID: id03sNvQ and USFWzMBr
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
}