views:

427

answers:

3

I wrote a little Linq like DSL on top of Google Collections

    public class IterableQuery {

   public static <T> Where<T> from(Iterable<T> originalCollection) {
      return  new Where<T>( Iterables.transform(originalCollection, IterableQuery.<T>SAME()));
   }

   private static <T> Function<T, T> SAME() {
      return new Function<T, T>(){
         public T apply(T arg0) {
            return arg0;
         }
      };
   }


   public static class SelectOrderBy<T>{

      private final Iterable<T> iterable;

      public SelectOrderBy(Iterable<T> iteable) {
         this.iterable = iteable;
      }

      public  SelectOrderBy<T> orderyBy( Comparator<T> sort ){
          Ordering.forComparator(sort).sort((List< ? extends T>) iterable);
          return new SelectOrderBy<T>( iterable);
      }

      public  <F> Iterable<F> select(  Function<? super T,? extends F> function){
         return Iterables.transform(iterable, function);
      }
      public  Iterable<T> selectEveryThing( ){
         return iterable;
      }
   }


   public static class Where<T>{

      private final Iterable<T> iterable;

      public Where(Iterable<T> iterable) {
         this.iterable = iterable;
      }

      public    SelectOrderBy<T> where(Predicate<T> predicate) {
         return  new SelectOrderBy<T>( Iterables.filter(iterable, predicate));
      }
   }

}

so I could do query collections in a more concise readable way

 Iterable<? extends NewOrder > currentlyAssigned = 
         IterableQuery.
          from(orders).
          where(placedInLast10Days).
          orderBy(lastName). 
          select(orderToNewOrder);

I am concerned whether this approach will cause an explosion of mini objects and cause some Garbage Collection issues( or any other issues) ?

+1  A: 

I think it depends on how transform behaves, if its like a lazy filter, i.e. you don't attach a reference to every result. then its more than OK object count wise. Garbage collection wise, you are not keeping any hidden references, once you lose the root reference the whole graph becomes unreachable and gets collected. way to go man this is really neat.

MahdeTo
+3  A: 

I believe Google Collections uses deferred execution for most of its Iterators. Deferred execution would minimize the number of intermediate objects created as it would eliminate most of the intermediate/temporary lists that could be created for each call (where, orderby, etc).

Basically, the each element returned by currentlyAssigned.iterator() isn't calculated until you call iterator.next(). Until then, your currentlyAssigned iterable is just a set of operations, nothing more.

Your only concern on the explosion of mini-objects if those objects last longer than the duration of a single element operation... peak memory usage could get quite big in that case and you could potentially run out of memory on very large lists or if you were converting objects (i.e. calling ToUpper() on all strings or something). This would only be the case if the result of where() was another list, then orderby() created another list, so on and so on.

As far as the GC handling many short lived objects, there's no problem. The modern Java garbage collector heavily optimized to handle that exact behavior.

James Schek
Confirmed that our iterators are always as lazy as possible, which wouldn't surprise you if you knew the guy who wrote most of them!
Kevin Bourrillion
A: 

The garbage collector has special code for short-lived objects, and they are very very cheap to use. Basically once in a while all reachable young objects are marked and every other object is reclaimed in one swoop.

Paul de Vrieze