1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.millscript.commons.util.list;
22
23 import java.io.Serializable;
24
25 import org.millscript.commons.util.IList;
26 import org.millscript.commons.util.ListIterator;
27 import org.millscript.commons.util.alerts.ListIndexOutOfBoundsAlert;
28 import org.millscript.commons.util.iterator.ArrayListIterator;
29 import org.millscript.commons.util.iterator.NullListIterator;
30 import org.millscript.commons.util.iterator.SharedArrayListIterator;
31
32 /**
33 * This class provides an immutable <code>List</code> implementation which is
34 * backed by a slice of an Object array. This class allows you to conveniently
35 * share store between different lists.
36 */
37 public class ISharedArrayList< V > extends AbstractIList< V > implements Cloneable, Serializable {
38
39 /**
40 * This is the ID from the release 0.1.0 for future compatibility.
41 */
42 private static final long serialVersionUID = 6049801407468696384L;
43
44 /**
45 * The index of the first element of this list in the backing store.
46 */
47 private final int firstIndex;
48
49 /**
50 * The index of the last element of this list in the backing store.
51 */
52 private final int lastIndex;
53
54 /**
55 * The backing store containing a fixed array of objects.
56 */
57 private final V[] store;
58
59 /**
60 * Constructs a new immutable array list with a slice of the specified
61 * backing object array.
62 *
63 * @param objects the backing object array(only kept if start <= end )
64 * @param start the index(one based, inclusive) of the first element in the
65 * slice
66 * @param end the index(one based, inclusive) of the last element in the
67 * slice. If end < start, the new list will be empty
68 */
69 public ISharedArrayList( final V[] objects, final int start, final int end ) {
70 if ( start > end ) {
71 this.store = null;
72 } else if ( start < 1 || start > objects.length ) {
73 throw new ListIndexOutOfBoundsAlert(
74 "First index in slice must be between 1 and the length of the array"
75 ).culprit(
76 "index",
77 start
78 ).decorate( objects ).mishap();
79 } else if ( end > objects.length ) {
80 throw new ListIndexOutOfBoundsAlert(
81 "Last index in slice must not be greater than the length of the array"
82 ).culprit(
83 "index",
84 end
85 ).decorate( objects ).mishap();
86 } else {
87 this.store = objects;
88 }
89 this.firstIndex = start;
90 this.lastIndex = end;
91 }
92
93 /**
94 * @see java.lang.Object#clone()
95 */
96 @Override
97 public Object clone() throws CloneNotSupportedException {
98
99 return super.clone();
100 }
101
102 /**
103 * @see org.millscript.commons.util.list.AbstractIList#doGet(int)
104 */
105 @Override
106 protected V doGet( final int pos ) {
107
108
109 return this.store[ this.firstIndex - 2 + pos ];
110 }
111
112 /**
113 * @see org.millscript.commons.util.list.AbstractIList#doSlice(int, int, boolean)
114 */
115 @Override
116 protected IList< V > doSlice( final int first, final int last, final boolean share ) {
117
118
119 if ( share ) {
120 return new ISharedArrayList< V >(
121 this.store,
122 this.firstIndex + first - 1,
123 this.firstIndex + last - 1
124 );
125 } else {
126 return new IArrayList< V >(
127 this.store,
128 this.firstIndex + first - 1,
129 this.firstIndex + last - 1
130 );
131 }
132 }
133
134 /**
135 * @see org.millscript.commons.util.IList#indexOf(java.lang.Object)
136 */
137 public int indexOf( final V value ) {
138 for ( int i = this.firstIndex - 1; i < this.lastIndex; i++ ) {
139 if ( value == null ? this.store[ i ] == null : value.equals( this.store[ i ] ) ) {
140 return i - this.firstIndex + 2;
141 }
142 }
143 return 0;
144 }
145
146 /**
147 * @see org.millscript.commons.util.IMap#iterator(boolean)
148 */
149 @SuppressWarnings( "unchecked" )
150 public ListIterator< V > iterator( final boolean share ) {
151 if ( share ) {
152 return new SharedArrayListIterator< V >(
153 this.store,
154 this.firstIndex,
155 this.lastIndex
156 );
157 } else if ( this.size() == 0 ) {
158 return new NullListIterator< V >();
159 } else {
160 final V[] objects = (V[]) new Object[ this.size() ];
161 System.arraycopy( this.store, this.firstIndex - 1, objects, 0, objects.length );
162 return new ArrayListIterator< V >( objects, true );
163 }
164 }
165
166 /**
167 * @see org.millscript.commons.util.IMap#size()
168 */
169 public int size() {
170 return this.lastIndex < this.firstIndex ? 0
171 : this.lastIndex - this.firstIndex + 1;
172 }
173
174 }