java集合:get对象是否被修改,添加和删除?

时间:2011-06-29 07:05:17

标签: java collections

是否有这样的集合实现可以让我们知道与特定点相比新添加,修改或删除的对象是什么?

我想使用这样的集合来保存从数据库加载的对象,并将其绑定到用户界面,这样用户就可以向其中添加新对象,删除其中的项目或修改某些对象。当用户单击保存按钮时,我需要将更改保留到数据库,因此我需要知道更改的对象。


这是我自己的解决方案,但我不确定它是否非常糟糕,请给我一些建议。

界面:

import java.util.Collection;

/**
 * @author ggfan@amarsoft
 *
 */
public interface DataObjectsMonitor {

    /**
     * take a snapshot for comparing
     */
    public void snapshot();

    /**
     * 
     * @return Objects that are modified comparing to those ones before {@link #snapshot()} last called
     */
    public Collection<?> getmodifiedObjects();

    /**
     * 
     * @return Objects that are deleted comparing to those ones before {@link #snapshot()} last called
     */
    public Collection<?> getDeletedObjects();

    /**
     * 
     * @return Objects that are added comparing to those ones before {@link #snapshot()} last called
     */
    public Collection<?> getAddedObjects();
}

模型类必须从这样的抽象类扩展:

public abstract class DataObject {

    public abstract int dataHashCode();

}

实施班:

public class DataObjectListMonitor<T extends DataObject> extends ArrayList<T> implements DataObjectsMonitor {

    private static final long serialVersionUID = 1L;

    private Map<T, Integer> oldVersion = new HashMap<T, Integer>();

    public void snapshot() {
        oldVersion.clear();
        for(T t : this){
            oldVersion.put(t, new Integer(t.dataHashCode()));
        }
    }

    public Collection<T> getmodifiedObjects() {
        ArrayList<T> modified = new ArrayList<T>();
        for(T t : oldVersion.keySet()){
            if(this.contains(t) && t.dataHashCode() != oldVersion.get(t)){
                modified.add(t);
            }
        }
        return modified;
    }

    public Collection<T> getDeletedObjects() {
        ArrayList<T> deleted = new ArrayList<T>();
        for(T t : oldVersion.keySet()){
            if(!this.contains(t)){
                deleted.add(t);
            }
        }
        return deleted;
    }

    public Collection<T> getAddedObjects() {
        ArrayList<T> added = new ArrayList<T>();
        for(T t : this){
            if(!oldVersion.keySet().contains(t)){
                added.add(t);
            }
        }
        return added;
    }

}

测试:

public class Model extends DataObject {
    private String id;

    private String name;

    public String toString() {
        return "Model [id=" + id + ", name=" + name + "]";
    }

    public Model(String id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int dataHashCode() {
        int dataHashCode = 0;
        if(id != null){
            dataHashCode += id.hashCode();
        }
        if(name != null){
            dataHashCode += name.hashCode();
        }
        return dataHashCode;
    }

    public static void main(String[] args){
        DataObjectListMonitor<Model> data = new DataObjectListMonitor<Model>();
        Model m1 = new Model("m1", "model 1");
        Model m2 = new Model("m2", "model 2");
        Model m3 = new Model("m3", "model 3");
        Model m4 = new Model("m4", "model 4");
        Model m5 = new Model("m5", "model 5");
        data.add(m1);
        data.add(m2);
        data.add(m3);
        data.add(m4);
        data.add(m5);
        data.snapshot();
        Model m6 = new Model("m6", "model 6");
        data.add(m6);
        m3.setName("model 3 changed");
        m3.setName("model 3");
        data.remove(m5);
        m1.setName("model 1 chaned");
        for(Model m : data.getAddedObjects()){
            System.out.println("added : " +  m);
        }

        for(Model m : data.getDeletedObjects()){
            System.out.println("deleted : " + m);
        }

        for(Model m : data.getmodifiedObjects()){
            System.out.println("modified : " + m);
        }
    }

}

输出:

added : Model [id=m6, name=model 6]
deleted : Model [id=m5, name=model 5]
modified : Model [id=m1, name=model 1 chaned]

编辑:使用hashCode是完全错误的,但也许我们可以使用MD5或CRC32。

4 个答案:

答案 0 :(得分:4)

您可以实现一个自定义集合,可以轻松跟踪和记录添加,替换和删除操作,但跟踪和记录对集合项的修改是非常不可能的..

总体思路:实现List接口,添加委托(真实列表)并将所有方法调用委托给内部列表(或set,map,queue,...):

public class LoggingList implements List {
  private List delegate = new ArrayList();
  private List<ChangeEvent> history = new ArrayList<ChangeEvent>();

  // ...

  @Override
  public boolean add(Object item) {
    boolean success = delegate.add(item);
    if (success) {
     history.add(new ChangeEvent(Type.ADD, item));
    }
    return success;
  }
}

但是 - 列表无法跟踪是否有人使用item引用来添加后修改其状态。

答案 1 :(得分:1)

一种方法是创建自己的集合,实现Map接口并为其添加脏标志。因此,当您从集合中添加或删除元素时,请将isDirty标志设为true并根据它执行操作。

如果现有对象发生了变化,那么你需要有一些不同的逻辑。

答案 2 :(得分:1)

在我看来,您不应该跟踪集合中的更改,而应该更改对象本身。因此,在对象中添加changed flag作为实例字段,并在更改内容后将其设置为true,并在将其写入数据库后将其设置为false

跟踪集合内部的问题是很难跟踪对集合中已有对象的修改。然后你需要像每个对象周围的包装器一样,当对象发生变化时“通知”你的集合。在我看来太多了,可以通过跟踪对象本身来解决这个问题。 之后可以使用此对象的状态来过滤集合或其他任何内容......

答案 3 :(得分:1)

跟踪修改意味着必须有一些ID可以附加到每个项目,这也意味着您更好的选择是Map而不是Collection

执行此操作的一个示例是子类HashMap并拦截put(用于添加/修改操作)和remove(用于删除操作)。

这是一般性的想法 - 最重要的是你最有可能自己实施,除非其他人可以推荐第三方API:

  Map<K, V> items = new HashMap<K, V>() {
    public V put(K key, V value) {
      if (containsKey(key))
        modified.put(key, value);
      else
        created.put(key, value);

      return super.put(key, value);
    }

    public V remove(Object key) {
      if (containsKey(key))
        deleted.put((K) key, get(key));

      return super.remove(key);
    }
  };