Initial prototype for BiStream (renamed to MapStream)
Peter Levart
peter.levart at gmail.com
Sun May 6 15:25:49 PDT 2012
Hi Mike, Brian,
I have experimented with a thechique that uses "push" instead of "pull" (like
Iterable or MapStream). Here's the result:
https://github.com/plevart/PushPipes
Pipe is a pair to Iterable
BiPipe is a pair to MapStream
I tried to implement most of the operations present in Iterable and MapStream.
There are pros and cons to this approach.
Pros:
- No box/unbox-ing of intermediate results (BiValue-s)
- The code for various operations seems to be much simpler
Con:
- References in the chain of operations are in direction parent -> child (as
opposed to child -> parent with pull approach of Iterator/MapStream), so each
parent can only have one child (you can not re-use half built chain to build
two different continuations).
What dou you think?
Regards, Peter
On Wednesday, April 25, 2012 05:33:31 PM Mike Duigou wrote:
> Or, if you are the type of person who likes to be their explanations to be
> entertaining:
>
> http://youtu.be/wbp-3BJWsU8?t=10m20s
>
> which was bug:
>
> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6312706
>
> Mike
>
> On Apr 25 2012, at 15:36 , Rémi Forax wrote:
> > Hi Peter,
> > The original implementation of IdentityHashMap was based on the same
> > idea, reusing Map.Entry implementation, and it didn't work well.
> >
> > Full story here:
> > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6232484
> >
> > Rémi
> >
> > On 04/26/2012 12:25 AM, Peter Levart wrote:
> >> On Wednesday, April 18, 2012 03:39:28 PM Mike Duigou wrote:
> >>> There's a big question lurking in the implementation involving
> >>> boxing/unboxing of BiValue<L,R> as used by the BiBlock, BiMapper and
> >>> Predicate.
> >>
> >> I don't know if this is a good idea, but pragmatic approach could be to
> >> re-use the intermediate BiValues and control manually if you need
> >> BiValue(s) by reference or just momentarily for extracting the
> >> components (i.e. whether the reference to BiValue "escapes" the
> >> iteration step or not).
> >>
> >> For example:
> >>
> >> public abstract class BiValueStream<T, U> implements Iterable<BiValue<T,
> >> U>> {
> >>
> >> private boolean reuseResult = true;
> >>
> >> private static class BiVal<T, U> implements BiValue<T, U>
> >> {
> >>
> >> private T left;
> >> private U right;
> >>
> >> @Override
> >> public T left()
> >> {
> >>
> >> return left;
> >>
> >> }
> >>
> >> @Override
> >> public U right()
> >> {
> >>
> >> return right;
> >>
> >> }
> >>
> >> }
> >>
> >> <V> BiValueStream<T, V> map(final BiMapper<T, U, V> mapper)
> >> {
> >>
> >> return new BiValueStream<T, V>()
> >> {
> >>
> >> @Override
> >> public Iterator<BiValue<T, V>> iterator()
> >> {
> >>
> >> final Iterator<BiValue<T, U>> source =
> >> BiValueStream.this.iterator();
> >>
> >> return new Iterator<BiValue<T, V>>()
> >> {
> >>
> >> @Override
> >> public boolean hasNext()
> >> {
> >>
> >> return source.hasNext();
> >>
> >> }
> >>
> >> private BiVal<T, V> reusableResult = reuseResult ? new
> >> BiVal<T, V>() : null;
> >>
> >> @Override
> >> public BiValue<T, V> next()
> >> {
> >>
> >> BiValue<T, U> next = source.next();
> >> BiVal<T, V> result = reuseResult ? reusableResult :
> >> new BiVal<T, V>();
> >> result.left = next.left();
> >> result.right = mapper.map(next.left(), next.right());
> >> return result;
> >>
> >> }
> >>
> >> };
> >>
> >> }
> >>
> >> };
> >>
> >> }
> >>
> >> public BiValueStream<T, U> reuseResult(boolean reuseResult)
> >> {
> >>
> >> this.reuseResult = reuseResult;
> >> return this;
> >>
> >> }
> >>
> >> }
> >>
> >>
> >> // an example where BiVal is resused:
> >>
> >> BiValueStream<String, String> keyVals = ...;
> >> Map<String, Integer> keyValLengths = new HashMap<>();
> >>
> >> for (BiValue<String, Integer> keyValLength : keyVals.map((key, val) ->
> >> key.length() + val.length())) {
> >>
> >> keyValLengths.put(keyValLength.left(), keyValLength.right());
> >>
> >> }
> >>
> >> // and where it is not:
> >>
> >> List<BiValue<String, Integer>> keyValLengthList = new ArrayList<>();
> >>
> >> for (BiValue<String, Integer> keyValLength : keyVals.map((key, val) ->
> >> key.length() + val.length()).reuseResult(false)) {
> >>
> >> keyValLengthList.add(keyValLength);
> >>
> >> }
> >>
> >>
> >> ...usually, when you chain transformations, you don't need intermediate
> >> BiValues by reference, just the components. Only at the end you may need
> >> them.
> >>
> >>
> >> Regards,
> >> Peter
More information about the lambda-dev
mailing list