添加元素时,属性更改事件的集合的旧值

时间:2017-10-01 09:32:28

标签: java javabeans propertychangelistener propertychangesupport

我有一个Java bean,它具有带getter的collection属性,并且还为该集合提供了添加方法。

因此,当使用add方法修改集合时,我必须触发PropertyChangeEventPropertyChangeEvent具有旧值和新值。

你如何处理旧的价值?

为了方便起见,我将在这里使用String的集合。 E.g。

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会返回true,但add也会返回true

在多线程环境中,首先检查via contains然后添加可能也是一个问题,因为同时另一个线程可能添加了相同的对象。但我不想在这里介绍这种复杂性。我只是想为单线程环境找到一个好的设计,通常是在UI中使用这样的bean时(Event-Dispatch-Thread)。

在这种情况下你如何处理旧价值?

1 个答案:

答案 0 :(得分:1)

您可以使用Map.putIfAbsent实现,并使密钥和值保持一致。

如果密钥存在,将返回先前(旧)值,并用于触发firePropertyChange。 这在多线程环境中运行良好,只有一个线程可以添加新条目。