如何最好地比较Java中的两个集合并对它们进行操作?

如何最好地比较Java中的两个集合并对它们进行操作?,java,collections,Java,Collections,我有两个相同对象的集合,Collection oldSet和Collection newSet。所需逻辑如下: 如果foo位于(*)oldSet而不是newSet,请调用doRemove(foo) 否则,如果foo不在oldSet中,而是在newSet中,请调用doAdd(foo) 否则,如果两个集合中都有foo但已修改,请调用doUpdate(oldFoo,newFoo) 否则,如果!foo.activated&&foo.startDate>=现在,调用doStart(foo) 否则,对于一

我有两个相同对象的集合,
Collection oldSet
Collection newSet
。所需逻辑如下:

  • 如果
    foo
    位于(*)
    oldSet
    而不是
    newSet
    ,请调用
    doRemove(foo)
  • 否则,如果
    foo
    不在
    oldSet
    中,而是在
    newSet
    中,请调用
    doAdd(foo)
  • 否则,如果两个集合中都有
    foo
    但已修改,请调用
    doUpdate(oldFoo,newFoo)
  • 否则,如果
    !foo.activated&&foo.startDate>=现在
    ,调用
    doStart(foo)

  • 否则,对于一个如此小的集合,如果
    foo.activated&&foo.endDate,通常不值得从数组转换为HashMap/集合。事实上,您最好将它们保存在一个数组中,然后按键对它们进行排序,并同时迭代两个列表以进行比较。

    我创建了一个近似值,我认为您只需要使用Java中的Collections框架就可以找到它。坦白地说,我认为正如@Mike Deck所指出的,这可能是矫枉过正。对于这样一个比较和处理的小项目集,我认为从过程的角度来看,数组是一个更好的选择,但这里是我的伪编码(因为我很懒)解决方案。我假设Foo类基于其唯一id而不是其内容中的所有数据具有可比性:

    Collection<Foo> oldSet = ...;
    Collection<Foo> newSet = ...;
    
    private Collection difference(Collection a, Collection b) {
        Collection result = a.clone();
        result.removeAll(b)
        return result;
    }
    
    private Collection intersection(Collection a, Collection b) {
        Collection result = a.clone();
        result.retainAll(b)
        return result;
    }
    
    public doWork() {
        // if foo is in(*) oldSet but not newSet, call doRemove(foo)
        Collection removed = difference(oldSet, newSet);
        if (!removed.isEmpty()) {
            loop removed {
                Foo foo = removedIter.next();
                doRemove(foo);
            }
        }
        //else if foo is not in oldSet but in newSet, call doAdd(foo)
        Collection added = difference(newSet, oldSet);
        if (!added.isEmpty()) {
            loop added  {
                Foo foo = addedIter.next();
                doAdd(foo);
            }
        }
    
        // else if foo is in both collections but modified, call doUpdate(oldFoo, newFoo)
        Collection matched = intersection(oldSet, newSet);
        Comparator comp = new Comparator() {
            int compare(Object o1, Object o2) {
                Foo f1, f2;
                if (o1 instanceof Foo) f1 = (Foo)o1;
                if (o2 instanceof Foo) f2 = (Foo)o2;
                return f1.activated == f2.activated ? f1.startdate.compareTo(f2.startdate) == 0 ? ... : f1.startdate.compareTo(f2.startdate) : f1.activated ? 1 : 0;
            }
    
            boolean equals(Object o) {
                 // equal to this Comparator..not used
            }
        }
        loop matched {
            Foo foo = matchedIter.next();
            Foo oldFoo = oldSet.get(foo);
            Foo newFoo = newSet.get(foo);
            if (comp.compareTo(oldFoo, newFoo ) != 0) {
                doUpdate(oldFoo, newFoo);
            } else {
                //else if !foo.activated && foo.startDate >= now, call doStart(foo)
                if (!foo.activated && foo.startDate >= now) doStart(foo);
    
                // else if foo.activated && foo.endDate <= now, call doEnd(foo)
                if (foo.activated && foo.endDate <= now) doEnd(foo);
            }
        }
    }
    
    Collection oldSet=。。。;
    收集新闻集=。。。;
    私有集合差异(集合a、集合b){
    收集结果=a.clone();
    结果:删除所有(b)
    返回结果;
    }
    私人集合交叉口(集合a、集合b){
    收集结果=a.clone();
    结果.保留(b)
    返回结果;
    }
    公共嫁妆{
    //如果foo在(*)oldSet中,但不在newSet中,则调用doRemove(foo)
    删除的集合=差异(旧集、新闻集);
    如果(!removed.isEmpty()){
    环移除{
    Foo-Foo=removedIter.next();
    多雷莫夫(富);
    }
    }
    //否则,如果foo不在oldSet中,而是在newSet中,则调用doAdd(foo)
    添加的集合=差异(新闻集、旧集);
    如果(!added.isEmpty()){
    循环添加{
    Foo-Foo=addedIter.next();
    doAdd(foo);
    }
    }
    //否则,如果两个集合中都有foo,但都已修改,则调用doUpdate(oldFoo、newFoo)
    集合匹配=交叉点(旧集、新集);
    比较器comp=新比较器(){
    int比较(对象o1、对象o2){
    Foo-f1,f2;
    如果(o1实例Foo)f1=(Foo)o1;
    如果(o2实例of Foo)f2=(Foo)o2;
    返回f1.activated==f2.activated?f1.startdate.compareTo(f2.startdate)==0?..:f1.startdate.compareTo(f2.startdate):f1.activated?1:0;
    }
    布尔等于(对象o){
    //等于此比较器..未使用
    }
    }
    回路匹配{
    Foo-Foo=matchedIter.next();
    Foo oldFoo=oldSet.get(Foo);
    Foo newFoo=newSet.get(Foo);
    如果(比较组件(旧版本、新版本)!=0){
    doUpdate(oldFoo、newFoo);
    }否则{
    //否则,如果!foo.activated&&foo.startDate>=now,则调用doStart(foo)
    如果(!foo.activated&&foo.startDate>=now)doStart(foo);
    
    //否则,如果foo.activated&&foo.endDate我将移动到列表并以这种方式解决它:

  • 如果列表中的对象不存在,则使用自定义按id升序对两个列表进行排序
  • 迭代两个列表中的元素,就像在合并阶段一样,但不是合并列表,而是检查逻辑
  • 代码大致如下所示:

    /* Main method */
    private void execute(Collection<Foo> oldSet, Collection<Foo> newSet) {
      List<Foo> oldList = asSortedList(oldSet);
      List<Foo> newList = asSortedList(newSet);
    
      int oldIndex = 0;
      int newIndex = 0;
      // Iterate over both collections but not always in the same pace
      while( oldIndex < oldList.size() 
          && newIndex < newIndex.size())  {
        Foo oldObject = oldList.get(oldIndex);
        Foo newObject = newList.get(newIndex);
    
        // Your logic here
        if(oldObject.getId() < newObject.getId()) {
          doRemove(oldObject);
          oldIndex++;
        } else if( oldObject.getId() > newObject.getId() ) {
          doAdd(newObject);
          newIndex++;
        } else if( oldObject.getId() == newObject.getId() 
                && isModified(oldObject, newObject) ) {
          doUpdate(oldObject, newObject);
          oldIndex++;
          newIndex++;
        } else {
          ... 
        }
      }// while
    
      // Check if there are any objects left in *oldList* or *newList*
    
      for(; oldIndex < oldList.size(); oldIndex++ ) {
        doRemove( oldList.get(oldIndex) );  
      }// for( oldIndex )
    
      for(; newIndex < newList.size(); newIndex++ ) {
        doAdd( newList.get(newIndex) );
      }// for( newIndex ) 
    }// execute( oldSet, newSet )
    
    /** Create sorted list from collection 
        If you actually perform any actions on input collections than you should 
        always return new instance of list to keep algorithm simple.
    */
    private List<Foo> asSortedList(Collection<Foo> data) {
      List<Foo> resultList;
      if(data instanceof List) {
         resultList = (List<Foo>)data;
      } else {
         resultList = new ArrayList<Foo>(data);
      }
      Collections.sort(resultList)
      return resultList;
    }
    
    /*主方法*/
    私有void执行(集合旧集、集合新闻集){
    列表oldList=分类列表(oldSet);
    List newList=分类列表(新闻集);
    int-oldIndex=0;
    int newIndex=0;
    //迭代两个集合,但不总是以相同的速度进行
    而(oldIndexnewObject.getId()){
    doAdd(新对象);
    newIndex++;
    }else if(oldObject.getId()==newObject.getId()
    &&isModified(旧对象、新对象)){
    doUpdate(旧对象、新对象);
    oldIndex++;
    newIndex++;
    }否则{
    ... 
    }
    }//当
    //检查*oldList*或*newList*中是否还有任何对象*
    对于(;oldIndex
    Apache的commons.collections库有一个CollectionUtils类,该类为集合操作/检查提供了易于使用的方法,例如交集、差集和并集


    org.apache.commons.collections.collections.CollectionUtils API文档是。

    我认为最简单的方法是使用apache collections API-CollectionUtils.subtract(list1,list2),只要列表类型相同。

    要制作列表或集合,我们可以使用
    Arrays.equals(object[],object[])
    。它将只检查值。要获取
    对象[]
    ,我们可以使用
    Collection.toArray()
    方法。

    例如,您可以使用Java 8流

    set1.stream().filter(s -> set2.contains(s)).collect(Collectors.toSet());
    
    或来自:
    Set<String> intersection = Sets.intersection(set1, set2);
    Set<String> difference = Sets.difference(set1, set2);
    Set<String> symmetricDifference = Sets.symmetricDifference(set1, set2);
    Set<String> union = Sets.union(set1, set2);
    
    public static boolean doCollectionsContainSameElements(
            Collection<Integer> c1, Collection<Integer> c2){
    
        if (c1 == null || c2 == null) {
            return false;
        }
        else if (c1.size() != c2.size()) {
            return false;
        } else {    
            return c1.containsAll(c2) && c2.containsAll(c1);
        }       
    }