1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.archive.util;
25
26
27 import java.io.Serializable;
28 import java.util.AbstractList;
29 import java.util.List;
30
31
32 /***
33 * Universal sublist implementation. Instances of this class are
34 * appropriate to return from {@link List#subList(int, int)}
35 * implementations.
36 *
37 * <p>This implementation is efficient if the super list is random-access.
38 * LinkedList-style super lists should subclass this and provide a custom
39 * iterator.
40 *
41 * @author pjack
42 * @param <E> the element type of the list
43 */
44 public class SubList<E> extends AbstractList<E> implements Serializable {
45
46 private static final long serialVersionUID = 1L;
47
48 /***
49 * The list that created this SubList.
50 */
51 final private List<E> delegate;
52
53 /***
54 * The starting index of the SubList, inclusive.
55 */
56 private int start;
57
58 /***
59 * The ending index of the SubList, exclusive.
60 */
61 private int end;
62
63
64 /***
65 * Constructor.
66 *
67 * @param delegate the list that create this SubList
68 * @param start the starting index of the sublist, inclusive
69 * @param end the ending index of the sublist, exclusive
70 * @throws IndexOutOfBoundsException if start or end are outside the
71 * bounds of the list
72 * @throws IllegalArgumentException if end is less than start
73 */
74 public SubList(List<E> delegate, int start, int end) {
75 if ((start < 0) || (start > delegate.size())) {
76 throw new IndexOutOfBoundsException();
77 }
78 if ((end < 0) || (end > delegate.size())) {
79 throw new IndexOutOfBoundsException();
80 }
81 if (end < start) {
82 throw new IllegalArgumentException();
83 }
84 this.delegate = delegate;
85 this.start = start;
86 this.end = end;
87 }
88
89 /***
90 * Ensures that the given index is strictly within the bounds of this
91 * SubList.
92 *
93 * @param index the index to check
94 * @throws IndexOutOfBoundsException if the index is out of bounds
95 */
96 private void ensureInside(int index) {
97 if ((index < 0) || (index >= end - start)) {
98 throw new IndexOutOfBoundsException();
99 }
100 }
101
102 /***
103 * Ensures that the given index is either within bounds or on the border
104 * of this SubList. In other words, this method allows the given index
105 * to be equal to {@link #size()}.
106 *
107 * @param index the index to check
108 * @throws IndexOutOfBoundsException if the index is out of bounds
109 */
110 private void ensureBorder(int index) {
111 if ((index < 0) || (index > end - start)) {
112 throw new IndexOutOfBoundsException();
113 }
114 }
115
116
117 @Override
118 public E get(int index) {
119 ensureInside(index);
120 return delegate.get(start + index);
121 }
122
123
124 @Override
125 public int size() {
126 return end - start;
127 }
128
129
130 @Override
131 public E set(int index, E value) {
132 ensureInside(index);
133 return delegate.set(start + index, value);
134 }
135
136
137 @Override
138 public void add(int index, E value) {
139 ensureBorder(index);
140 delegate.add(start + index, value);
141 end++;
142 }
143
144
145 @Override
146 public E remove(int index) {
147 ensureInside(index);
148 return delegate.remove(start + index);
149 }
150 }