Skip to content

Commit 01e1d13

Browse files
committed
Small improvements to IndexedSet
1 parent 55d0876 commit 01e1d13

File tree

1 file changed

+30
-31
lines changed
  • core/src/main/java/ai/timefold/solver/core/impl/bavet/common/index

1 file changed

+30
-31
lines changed

core/src/main/java/ai/timefold/solver/core/impl/bavet/common/index/IndexedSet.java

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)