如果您希望 Map 在 OtherClass 对象的 id 被修改时自动更新,那么您需要自己编写代码。
除非地图和对象紧密耦合,否则您应该保持逻辑解耦,例如通过实施属性更改跟踪。
我建议围绕 Java 运行时库中的 PropertyChangeSupport 类构建它。
其他类
首先您需要启用属性更改跟踪。
我添加了name 属性以改进此答案末尾的测试代码输出。
public final class OtherClass {
private final transient PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private int id;
private String name;
public OtherClass(int id, String name) {
this.id = id;
this.name = name;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
this.pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
this.pcs.removePropertyChangeListener(listener);
}
public int getId() {
return this.id;
}
public void setId(int id) {
int oldId = this.id;
this.id = id;
this.pcs.firePropertyChange("id", oldId, id);
}
public String getName() {
return this.name;
}
public void setName(String name) {
String oldName = this.name;
this.name = name;
this.pcs.firePropertyChange("name", oldName, name);
}
@Override
public String toString() {
return "OtherClass[" + this.id + ", " + this.name + "]";
}
}
其他地图
接下来需要封装Map,这样才能正确处理属性变化监听器。
为了防止内存泄漏,当不再需要 clear() 和 OtherMap 时很重要,否则对 OtherMap 中的单个 OtherMap 对象的引用将保留映射和所有对象在地图上活在记忆中。为了解决这个问题,我创建了对象 AutoCloseable,因此它可以与 try-with-resources 语句一起使用,并使代码分析器有助于突出关闭/清除地图的需要。
final class OtherMap implements AutoCloseable {
private final PropertyChangeListener listener = this::onPropertyChange;
private Map<Integer, OtherClass> map = new HashMap<>();
public OtherMap() {
}
public Set<Integer> keys() {
return Collections.unmodifiableSet(this.map.keySet());
}
public Collection<OtherClass> values() {
return Collections.unmodifiableCollection(this.map.values());
}
public OtherClass get(int id) {
return this.map.get(id);
}
public OtherClass add(OtherClass other) {
OtherClass prev = this.map.put(other.getId(), other);
if (prev != null)
prev.removePropertyChangeListener(this.listener);
other.addPropertyChangeListener(this.listener);
return prev;
}
public OtherClass remove(int id) {
OtherClass other = this.map.remove(id);
if (other != null)
other.removePropertyChangeListener(this.listener);
return other;
}
public void clear() {
this.map.values().forEach(other -> other.removePropertyChangeListener(this.listener));
this.map.clear();
}
private void onPropertyChange(PropertyChangeEvent evt) {
if (! "id".equals(evt.getPropertyName()))
return;
Integer oldId = (Integer) evt.getOldValue();
Integer newId = (Integer) evt.getNewValue();
if (oldId.equals(newId))
return;
OtherClass other = (OtherClass) evt.getSource();
if (this.map.putIfAbsent(newId, other) != null)
throw new IllegalStateException("Duplicate key");
if (! this.map.remove(oldId, other)) {
this.map.remove(newId);
throw new IllegalStateException();
}
}
@Override
public String toString() {
return this.map.toString();
}
@Override
public void close() {
clear();
}
}
测试
OtherClass eeny = new OtherClass(3, "Eeny");
OtherClass meeny = new OtherClass(5, "Meeny");
OtherClass miny = new OtherClass(7, "Miny");
OtherClass moe = new OtherClass(9, "Moe");
OtherMap otherMap = new OtherMap();
otherMap.add(eeny);
otherMap.add(meeny);
otherMap.add(miny);
otherMap.add(moe);
System.out.println("Before: " + otherMap);
meeny.setId(2);
otherMap.remove(miny.getId());
miny.setId(4);
System.out.println("After: " + otherMap);
输出
Before: {3=OtherClass[3, Eeny], 5=OtherClass[5, Meeny], 7=OtherClass[7, Miny], 9=OtherClass[9, Moe]}
After: {2=OtherClass[2, Meeny], 3=OtherClass[3, Eeny], 9=OtherClass[9, Moe]}