属性 添加元素时更改集合事件的旧值
Property change event's old value for collections when element is added
我有一个 Java bean,它有一个集合 属性 和一个 getter 并且还提供了集合的添加方法。
因此,当使用 add
方法修改集合时,我必须触发 PropertyChangeEvent
。 PropertyChangeEvent
有一个旧值和一个新值。
你如何处理旧值?
为了方便起见,我将在这里使用 String
的集合。例如
public class MyBean {
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private Set<String> names = new HashSet();
// Delegate methods to add/remove PropertyChangeListeners are omitted here
/**
* The collection property
*/
public Collection<String> getNames() {
return Collections.unmodifiableCollection(names);
}
public void addName(String name){
if(names.add(name)){
Collection<String> oldValue = ????; // How do you get the old value
Collection<String> newValue = Collections.unmodifiableCollection(names);
pcs.firePropertyChange("names", oldValue, newValue);
}
}
}
获取旧值的一种方法可能是在添加之前创建一个副本
public void addName(String name) {
Collection<String> oldValue = new HashSet<>(names);
if (names.add(name)) {
Collection<String> newValue = Collections.unmodifiableCollection(names);
pcs.firePropertyChange("names", oldValue, newValue);
}
}
但在很多情况下,旧值可能会被白白复制。
所以另一个想法是不使用 add 方法,而是在
之前使用 contains
public void addName(String name) {
if (names.contains(name)) {
return;
}
Collection<String> oldValue = new HashSet<>(names);
names.add(name);
Collection<String> newValue = Collections.unmodifiableCollection(names);
pcs.firePropertyChange("names", oldValue, newValue);
}
这适用于 Set
。但是当 names
集合是 ArrayList
时它将不起作用,因为 ArrayList
可以包含相同对象的多个实例。所以 contains
会 return 为真,但是 add
也会 return true
.
在多线程环境中,首先通过包含检查然后添加也可能是一个问题,因为与此同时另一个线程可能已经添加了相同的对象。但我不想在这里介绍这种复杂性。我只是想为单线程环境找到一个好的设计,通常在UI(Event-Dispatch-Thread)中使用此类bean时。
在这种情况下,您如何处理旧值?
可以使用Map.putIfAbsent
实现,键值相同。
如果密钥存在,将返回之前的(旧)值,并用于触发 firePropertyChange
。
这在多线程环境中运行良好,只有一个线程能够添加一个新条目。
我有一个 Java bean,它有一个集合 属性 和一个 getter 并且还提供了集合的添加方法。
因此,当使用 add
方法修改集合时,我必须触发 PropertyChangeEvent
。 PropertyChangeEvent
有一个旧值和一个新值。
你如何处理旧值?
为了方便起见,我将在这里使用 String
的集合。例如
public class MyBean {
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private Set<String> names = new HashSet();
// Delegate methods to add/remove PropertyChangeListeners are omitted here
/**
* The collection property
*/
public Collection<String> getNames() {
return Collections.unmodifiableCollection(names);
}
public void addName(String name){
if(names.add(name)){
Collection<String> oldValue = ????; // How do you get the old value
Collection<String> newValue = Collections.unmodifiableCollection(names);
pcs.firePropertyChange("names", oldValue, newValue);
}
}
}
获取旧值的一种方法可能是在添加之前创建一个副本
public void addName(String name) {
Collection<String> oldValue = new HashSet<>(names);
if (names.add(name)) {
Collection<String> newValue = Collections.unmodifiableCollection(names);
pcs.firePropertyChange("names", oldValue, newValue);
}
}
但在很多情况下,旧值可能会被白白复制。
所以另一个想法是不使用 add 方法,而是在
之前使用contains
public void addName(String name) {
if (names.contains(name)) {
return;
}
Collection<String> oldValue = new HashSet<>(names);
names.add(name);
Collection<String> newValue = Collections.unmodifiableCollection(names);
pcs.firePropertyChange("names", oldValue, newValue);
}
这适用于 Set
。但是当 names
集合是 ArrayList
时它将不起作用,因为 ArrayList
可以包含相同对象的多个实例。所以 contains
会 return 为真,但是 add
也会 return true
.
在多线程环境中,首先通过包含检查然后添加也可能是一个问题,因为与此同时另一个线程可能已经添加了相同的对象。但我不想在这里介绍这种复杂性。我只是想为单线程环境找到一个好的设计,通常在UI(Event-Dispatch-Thread)中使用此类bean时。
在这种情况下,您如何处理旧值?
可以使用Map.putIfAbsent
实现,键值相同。
如果密钥存在,将返回之前的(旧)值,并用于触发 firePropertyChange
。
这在多线程环境中运行良好,只有一个线程能够添加一个新条目。