- カスタム Map クラス内に 2 つのマップ フィールドを保持
originalMap
し、temporaryMap
.
- 読み取り操作は に委任され
originalMap
、書き込み操作は に委任されtemporaryMap
ます。
rollback()
への浅いコピーoriginalMap
、temporaryMap
およびcommit()
その逆。キーと値は複製されないため、参照のみが保持され、メモリは「無駄」になりません。
package com.example;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import lombok.NonNull;
import lombok.ToString;
@ToString
public class TransactionalMap<K, V> implements Map<K, V> {
private Map<K, V> originalMap;
private Map<K, V> temporaryMap;
public TransactionalMap() {
this(new HashMap<>());
}
public TransactionalMap(@NonNull Map<K, V> impl) {
if (impl instanceof TransactionalMap) {
throw new IllegalArgumentException("Must provide valid implementation instance");
}
this.originalMap = new HashMap<>(impl);
this.temporaryMap = new HashMap<>(originalMap);
}
@Override
public int size() {
return originalMap.size();
}
@Override
public boolean isEmpty() {
return originalMap.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return originalMap.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return originalMap.containsValue(value);
}
@Override
public V get(Object key) {
return originalMap.get(key);
}
@Override
public V put(K key, V value) {
return temporaryMap.put(key, value);
}
@Override
public V remove(Object key) {
return temporaryMap.remove(key);
}
@Override
public void putAll(Map<? extends K, ? extends V> m) {
temporaryMap.putAll(m);
}
@Override
public void clear() {
temporaryMap.clear();
}
@Override
public Set<K> keySet() {
return originalMap.keySet();
}
@Override
public Collection<V> values() {
return originalMap.values();
}
@Override
public Set<Entry<K, V>> entrySet() {
return originalMap.entrySet();
}
private void sync(Map<K, V> src, Map<K, V> tgt) {
tgt.putAll(src);
tgt.forEach((k, v) -> {
if (!src.containsKey(k)) tgt.remove(k);
});
}
public void commit() {
sync(temporaryMap, originalMap);
}
public void rollback() {
sync(originalMap, temporaryMap);
}
}
ロンボクを使用してボイラープレート コードを生成する