|
11 | 11 | import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; |
12 | 12 | import ai.timefold.solver.core.impl.util.MutableInt; |
13 | 13 |
|
14 | | -public final class MinMaxUndoableActionable<Result_, Property_> implements UndoableActionable<Result_> { |
| 14 | +public abstract class AbstractMinMaxSlot<Result_, Property_> { |
15 | 15 | public static final class State<Result_, Property_> { |
16 | 16 | final boolean isMin; |
17 | 17 | final NavigableMap<Property_, Map<Result_, MutableInt>> propertyToItemCountMap; |
@@ -69,35 +69,42 @@ public static <Result, Property extends Comparable<? super Property>> State<Resu |
69 | 69 | private Map<Result_, MutableInt> cachedInnerMap; |
70 | 70 | private MutableInt cachedCount; |
71 | 71 |
|
72 | | - public MinMaxUndoableActionable(State<Result_, Property_> state) { |
| 72 | + public AbstractMinMaxSlot(State<Result_, Property_> state) { |
73 | 73 | this.state = state; |
74 | 74 | } |
75 | 75 |
|
76 | | - @Override |
77 | | - public void insert(Result_ item) { |
| 76 | + protected void addMapped(Result_ item) { |
78 | 77 | cachedItem = item; |
79 | 78 | cachedKey = state.propertyFunction.apply(item); |
80 | 79 | cachedInnerMap = state.propertyToItemCountMap.computeIfAbsent(cachedKey, ignored -> new LinkedHashMap<>()); |
81 | 80 | cachedCount = cachedInnerMap.computeIfAbsent(item, ignored -> new MutableInt()); |
82 | 81 | cachedCount.increment(); |
83 | 82 | } |
84 | 83 |
|
85 | | - @Override |
86 | | - public void update(Result_ item) { |
| 84 | + protected void updateMapped(Result_ item) { |
87 | 85 | var newKey = state.propertyFunction.apply(item); |
88 | 86 | if (Objects.equals(cachedKey, newKey)) { |
| 87 | + if (Objects.equals(cachedItem, item)) { |
| 88 | + return; |
| 89 | + } |
| 90 | + // same key, different item: swap within the same inner map |
| 91 | + if (cachedCount.decrement() == 0) { |
| 92 | + cachedInnerMap.remove(cachedItem); |
| 93 | + } |
| 94 | + cachedItem = item; |
| 95 | + cachedCount = cachedInnerMap.computeIfAbsent(item, ignored -> new MutableInt()); |
| 96 | + cachedCount.increment(); |
89 | 97 | return; |
90 | 98 | } |
91 | | - retract(); |
| 99 | + removeMapped(); |
92 | 100 | cachedItem = item; |
93 | 101 | cachedKey = newKey; |
94 | 102 | cachedInnerMap = state.propertyToItemCountMap.computeIfAbsent(newKey, ignored -> new LinkedHashMap<>()); |
95 | 103 | cachedCount = cachedInnerMap.computeIfAbsent(item, ignored -> new MutableInt()); |
96 | 104 | cachedCount.increment(); |
97 | 105 | } |
98 | 106 |
|
99 | | - @Override |
100 | | - public void retract() { |
| 107 | + protected void removeMapped() { |
101 | 108 | if (cachedCount.decrement() == 0) { |
102 | 109 | cachedInnerMap.remove(cachedItem); |
103 | 110 | if (cachedInnerMap.isEmpty()) { |
|
0 commit comments