@@ -50,7 +50,7 @@ public final class IndexedSet<T> {
5050 static final double GAP_RATIO_FOR_COMPACTION = 0.1 ;
5151
5252 private final ElementPositionTracker <T > elementPositionTracker ;
53- private @ Nullable ArrayList <@ Nullable T > elementList ; // Lazily initialized, so that empty indexes use no memory.
53+ private @ Nullable List <@ Nullable T > elementList ; // Lazily initialized, so that empty indexes use no memory.
5454 private int lastElementPosition = -1 ;
5555 private int gapCount = 0 ;
5656
@@ -97,33 +97,39 @@ public void remove(T element) {
9797 }
9898
9999 private boolean innerRemove (T element ) {
100- if (isEmpty ()) {
101- return false ;
102- }
103100 var insertionPosition = elementPositionTracker .clearPosition (element );
104101 if (insertionPosition < 0 ) {
105102 return false ;
106103 }
107- var actualElementList = getElementList ();
108104 if (insertionPosition == lastElementPosition ) {
109105 // The element was the last one added; we can simply remove it.
110- actualElementList .remove (insertionPosition );
106+ elementList .remove (insertionPosition );
111107 lastElementPosition --;
112108 } else {
113109 // We replace the element with null, creating a gap.
114- actualElementList .set (insertionPosition , null );
110+ elementList .set (insertionPosition , null );
115111 gapCount ++;
116112 }
117113 clearIfPossible ();
118114 return true ;
119115 }
120116
117+ private boolean clearIfPossible () {
118+ if (gapCount > 0 && lastElementPosition + 1 == gapCount ) { // All positions are gaps. Clear the list entirely.
119+ elementList .clear ();
120+ gapCount = 0 ;
121+ lastElementPosition = -1 ;
122+ return true ;
123+ }
124+ return false ;
125+ }
126+
121127 public boolean isEmpty () {
122128 return size () == 0 ;
123129 }
124130
125131 public int size () {
126- return elementList == null ? 0 : lastElementPosition - gapCount + 1 ;
132+ return lastElementPosition - gapCount + 1 ;
127133 }
128134
129135 /**
@@ -197,42 +203,35 @@ private boolean shouldCompact() {
197203 return null ;
198204 }
199205
200- private boolean clearIfPossible () {
201- if (gapCount > 0 && lastElementPosition + 1 == gapCount ) {
202- // All positions are gaps. Clear the list entirely.
203- elementList .clear ();
204- gapCount = 0 ;
205- lastElementPosition = -1 ;
206- return true ;
207- }
208- return false ;
209- }
210-
211206 /**
212207 * Fills the gap at position i by moving the last element into it.
213208 *
214209 * @param gapPosition the position of the gap to fill
215210 * @return the element that now occupies position i, or null if no element further in the list can fill the gap
216211 */
217212 private @ Nullable T fillGap (int gapPosition ) {
218- T lastRemovedElement = null ;
219- while (lastElementPosition >= gapPosition ) {
220- lastRemovedElement = elementList .remove (lastElementPosition );
221- lastElementPosition --;
222- gapCount --; // Even if this is not a gap, we still mark a gap as removed...
223- if (lastRemovedElement != null ) {
224- break ;
225- }
226- }
213+ T lastRemovedElement = removeLastNonGap (gapPosition );
227214 if (lastRemovedElement == null ) {
228215 return null ;
229216 }
230- // ... because this actually fills the main gap we were asked to fill.
231217 elementList .set (gapPosition , lastRemovedElement );
232218 elementPositionTracker .setPosition (lastRemovedElement , gapPosition );
219+ gapCount --;
233220 return lastRemovedElement ;
234221 }
235222
223+ private @ Nullable T removeLastNonGap (int gapPosition ) {
224+ while (lastElementPosition >= gapPosition ) {
225+ var lastRemovedElement = elementList .remove (lastElementPosition );
226+ lastElementPosition --;
227+ if (lastRemovedElement != null ) {
228+ return lastRemovedElement ;
229+ }
230+ gapCount --;
231+ }
232+ return null ;
233+ }
234+
236235 /**
237236 * As defined by {@link #forEach(Consumer)},
238237 * but stops when the predicate returns true for an element.
@@ -270,8 +269,8 @@ private void forceCompaction() {
270269 for (var i = 0 ; i <= lastElementPosition ; i ++) {
271270 var element = elementList .get (i );
272271 if (element == null ) {
273- element = fillGap (i );
274- if (element == null || gapCount == 0 ) { // If there are no more gaps, we can stop.
272+ fillGap (i );
273+ if (gapCount == 0 ) { // If there are no more gaps, we can stop.
275274 return ;
276275 }
277276 }
0 commit comments