【问题标题】:java collection: get objects are modified, added and deleted?java集合:get对象被修改、添加和删除?
【发布时间】:2011-06-29 07:05:16
【问题描述】:

有没有这样的集合实现可以让我们知道与特定点相比,新增、修改或删除了哪些对象?

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


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

界面:

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。

【问题讨论】:

    标签: java collections


    【解决方案1】:

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

    总体思路:实现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,或修改一些绝对是这里的棘手。
    • 非常感谢您,我已经编辑了我的帖子,请给我更多建议。
    【解决方案2】:

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

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

    【讨论】:

    • 非常感谢您,我已经编辑了我的帖子,请给我更多建议。
    【解决方案3】:

    跟踪修改意味着您必须为每个项目附加一些 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);
        }
      };
    

    【讨论】:

    • 非常感谢您,我已经编辑了我的帖子,请给我更多建议。
    【解决方案4】:

    在我看来,您不应该跟踪集合中的更改,而应该跟踪更改的对象本身。所以在你的对象中有一个changed flag作为实例字段,并在发生变化时将其设置为true,并在将其写入数据库后将其设置为false

    在集合内部跟踪的问题是很难跟踪对集合中已有对象的修改。然后,您需要一个围绕每个对象的包装器,当该对象发生更改时“通知”您的集合。当这可以通过跟踪对象本身来解决时,我认为太多了。 该对象的状态随后可用于过滤集合或其他...

    【讨论】:

    • 非常感谢您,我已经编辑了我的帖子,请给我更多建议。
    猜你喜欢
    • 2012-01-12
    • 1970-01-01
    • 2013-05-03
    • 1970-01-01
    • 1970-01-01
    • 2015-08-18
    • 2013-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多