如何最好地比较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; }
Apache的commons.collections库有一个CollectionUtils类,该类为集合操作/检查提供了易于使用的方法,例如交集、差集和并集/*主方法*/ 私有void执行(集合旧集、集合新闻集){ 列表oldList=分类列表(oldSet); List newList=分类列表(新闻集); int-oldIndex=0; int newIndex=0; //迭代两个集合,但不总是以相同的速度进行 而(oldIndex
newObject.getId()){ doAdd(新对象); newIndex++; }else if(oldObject.getId()==newObject.getId() &&isModified(旧对象、新对象)){ doUpdate(旧对象、新对象); oldIndex++; newIndex++; }否则{ ... } }//当 //检查*oldList*或*newList*中是否还有任何对象* 对于(;oldIndex
org.apache.commons.collections.collections.CollectionUtils API文档是。我认为最简单的方法是使用apache collections API-CollectionUtils.subtract(list1,list2),只要列表类型相同。要制作列表或集合,我们可以使用
。它将只检查值。要获取Arrays.equals(object[],object[])
,我们可以使用对象[]
方法。例如,您可以使用Java 8流Collection.toArray()
或来自: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); } }