1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.collections15.list;
17
18 import java.util.List;
19
20 import net.sf.collections15.Factory;
21
22 /***
23 * Decorates another <code>List</code> to create objects in the list on demand.
24 * <p>
25 * When the {@link #get(int)} method is called with an index greater than
26 * the size of the list, the list will automatically grow in size and return
27 * a new object from the specified factory. The gaps will be filled by null.
28 * If a get method call encounters a null, it will be replaced with a new
29 * object from the factory. Thus this list is unsuitable for storing null
30 * objects.
31 * <p>
32 * For instance:
33 *
34 * <pre>
35 * Factory<Date> factory = new Factory<Date>() {
36 * public Date create() {
37 * return new Date();
38 * }
39 * }
40 * List<Date> lazy = LazyList.<Date>decorate(new ArrayList<Date>(), factory);
41 * Date obj = lazy.get(3);
42 * </pre>
43 *
44 * After the above code is executed, <code>obj</code> will contain
45 * a new <code>Date</code> instance. Furthermore, that <code>Date</code>
46 * instance is the fourth element in the list. The first, second,
47 * and third element are all set to <code>null</code>.
48 * <p>
49 * This class is Serializable from Commons Collections 3.1.
50 *
51 * @since Commons Collections 3.0
52 * @version $Revision: 1.2 $ $Date: 2005/05/25 21:25:25 $
53 *
54 * @author Stephen Colebourne
55 * @author Arron Bates
56 * @author Paul Jack
57 */
58 public class LazyList<E> extends AbstractSerializableListDecorator<E> {
59
60 /*** Serialization version */
61 private static final long serialVersionUID = 3760563096313738293L;
62
63 /*** The factory to use to lazily instantiate the objects */
64 protected final Factory<? extends E> factory;
65
66 /***
67 * Factory method to create a lazily instantiating list.
68 *
69 * @param list the list to decorate, must not be null
70 * @param factory the factory to use for creation, must not be null
71 * @throws IllegalArgumentException if list or factory is null
72 */
73 public static <T> List<T> decorate(List<T> list, Factory<? extends T> factory) {
74 return new LazyList<T>(list, factory);
75 }
76
77
78 /***
79 * Constructor that wraps (not copies).
80 *
81 * @param list the list to decorate, must not be null
82 * @param factory the factory to use for creation, must not be null
83 * @throws IllegalArgumentException if list or factory is null
84 */
85 protected LazyList(List<E> list, Factory<? extends E> factory) {
86 super(list);
87 if (factory == null) {
88 throw new IllegalArgumentException("Factory must not be null");
89 }
90 this.factory = factory;
91 }
92
93
94 /***
95 * Decorate the get method to perform the lazy behaviour.
96 * <p>
97 * If the requested index is greater than the current size, the list will
98 * grow to the new size and a new object will be returned from the factory.
99 * Indexes in-between the old size and the requested size are left with a
100 * placeholder that is replaced with a factory object when requested.
101 *
102 * @param index the index to retrieve
103 */
104 public E get(int index) {
105 int size = getList().size();
106 if (index < size) {
107
108 E object = getList().get(index);
109 if (object == null) {
110
111 object = factory.create();
112 getList().set(index, object);
113 return object;
114 } else {
115
116 return object;
117 }
118 } else {
119
120 for (int i = size; i < index; i++) {
121 getList().add(null);
122 }
123
124 E object = factory.create();
125 getList().add(object);
126 return object;
127 }
128 }
129
130
131 public List<E> subList(int fromIndex, int toIndex) {
132 List<E> sub = getList().subList(fromIndex, toIndex);
133 return new LazyList<E>(sub, factory);
134 }
135 }