Initial prototype for BiStream

Peter Levart peter.levart at gmail.com
Wed Apr 25 15:25:32 PDT 2012


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