LazyList based on the Google Collections Library

In my previous post I mentioned implementing the Google Collections counterpart of the commons-collections LazyList. I'll refer to the Google Collections Library as GCL from now on.

The LazyList decorates another List to create objects in the list on demand. To code below is loosly based on the code in commond-collections' lazylist counterpart. Most modifications are generics related.

Since GCL supplies a 'Forwarding' wrappers it's really easy to write a decorator for the List type. Extend from ForwardingList and override the needed methods:

JAVA:
  1. package com.finalist.collections.lazy;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import com.finalist.collections.factories.Factory;
  7. import com.google.common.collect.ForwardingList;
  8.  
  9. /**
  10. * Decorates another <code>List</code> to create objects in the list on
  11. * demand. Code loosly based on the code in commond-collections' lazylist
  12. * counterpart. Using the forwardinglist provided by Googles' Collection library
  13. *
  14. * When the {@link #get(int)} method is called with an index greater than the
  15. * size of the list, the list will automatically grow in size and return a new
  16. * object from the specified factory. The gaps will be filled by null. If a get
  17. * method call encounters a null, it will be replaced with a new object from the
  18. * factory. Thus this list is unsuitable for storing null objects.
  19. *
  20. * @author Peter Maas
  21. *
  22. * @param <T> Type of the objects contained in the list
  23. */
  24. public class LazyList<T> extends ForwardingList<T> {
  25.     private static final long serialVersionUID = 1;
  26.     private Factory<T> factory;
  27.  
  28.     protected LazyList(Factory<T> factory) {
  29.         super(new ArrayList<T>());
  30.         this.factory = factory;
  31.     }
  32.  
  33.     protected LazyList(List<T> delegate, Factory<T> factory) {
  34.         super(delegate);
  35.         this.factory = factory;
  36.     }
  37.  
  38.     public static <D> LazyList<D> decorate(List<D> delegate, Factory<D> factory) {
  39.         return new LazyList<D>(delegate, factory);
  40.     }
  41.  
  42.     /*
  43.      * (non-Javadoc)
  44.      *
  45.      * @see com.google.common.collect.ForwardingList#get(int)
  46.      */
  47.     public T get(int index) {
  48.         int size = delegate().size();
  49.         if (index <size) {
  50.             // within bounds, get the object
  51.             T object = delegate().get(index);
  52.             if (object == null) {
  53.                 // item is a place holder, create new one, set and return
  54.                 object = factory.create();
  55.                 delegate().set(index, object);
  56.                 return object;
  57.             } else {
  58.                 // good and ready to go
  59.                 return object;
  60.             }
  61.         } else {
  62.             // we have to grow the list
  63.             for (int i = size; i <index; i++) {
  64.                 delegate().add(null);
  65.             }
  66.             // create our last object, set and return
  67.             T object = factory.create();
  68.             delegate().add(object);
  69.             return object;
  70.         }
  71.     }
  72.  
  73.     /*
  74.      * (non-Javadoc)
  75.      *
  76.      * @see com.google.common.collect.ForwardingList#subList(int, int)
  77.      */
  78.     public List<T> subList(int fromIndex, int toIndex) {
  79.         List<T> sub = delegate().subList(fromIndex, toIndex);
  80.         return new LazyList<T>(sub, factory);
  81.     }
  82. }

As you can see I modified code from the commons-collections counterpart to use generics. I reimplemented parts of commons-collections' factory structure to use generics as well.

The next test concludes in success:

JAVA:
  1. package com.finalist.collections.lazy;
  2.  
  3. import java.util.List;
  4. import com.finalist.collections.factories.FactoryUtils;
  5. import junit.framework.TestCase;
  6.  
  7. public class LazyListTest extends TestCase {
  8.  
  9.     /**
  10.      * Test for the get(int) method of the LazyList
  11.      */
  12.     public void testGetInt() {
  13.         List<Dummy> dummyList = new LazyList<Dummy>(FactoryUtils.instantiateFactory(Dummy.class));
  14.        
  15.         // initially the list should be empty
  16.         assertEquals(0, dummyList.size());
  17.        
  18.         // accessing indexes directly should not result in index-out-of-bounds exceptions
  19.         assertNotNull(dummyList.get(0));
  20.         assertNotNull(dummyList.get(10));
  21.        
  22.         // size should now be 11:
  23.         assertEquals(11, dummyList.size());
  24.        
  25.         // the spaces between the to requested indexes should be populated with
  26.         // null values:
  27.         assertTrue(dummyList.contains(null));
  28.         assertEquals(1, dummyList.indexOf(null));
  29.     }
  30.  
  31. }

Please note that the above isn't a showcase for the features of GCL, its' a simple extension to add a LazyList implementation. Feel free to use or extend it!

full sources, test and buildfile


4 Responses to “LazyList based on the Google Collections Library”

  1. 1 erikvanoosten

    Regarding

    // we have to grow the list
    for (int i = size; i

  2. 2 erikvanoosten

    Right, my message was truncated!

  3. 3 erikvanoosten

    My point was: when you are growing the list, you may want to use the potentially more efficient addAll. In particular when you're adding to an ArrayList, the array can be resized in advance. Growing arrays is often a big performance hit in Java programs.

    You only need to device some smart immutable collection that returns the right amount of nulls.

  4. 4 erikvanoosten

    Otherwise: nice post (sorry, forgot to say that in the other comment).

Leave a Reply





About

Welcome to the weblog of Peter Maas. Here you'll find various posts related to stuff I like (like my kids and espresso) and stuff I do (like developing software).

JavaOne 2008 Pictures

koe golden_gate_warning_sign IMG_6130 sfeervolverlichte boot IMG_4684.JPG breun raadhuis_hilversum Danielle op de bruggen van Beeld en Geluid IMG_4705.JPG _MG_8016 starbucks zed shaw IMG_4590 kikker (frog) bridge mga dashboard Golden Gate bee on yellow flower Sjoerd op zonnig bospad Rudie
View more photos >

Categories



Meld u aan voor PayPal en begin direct met het accepteren van creditcardbetalingen.