我有2个列表按照特定顺序排列到我的方法中(根据ID字段升序或降序)
我有一个自定义比较器实现,允许我将两个列表都放入树集中并实现所需的结果。
我的问题是在加载treeset之后,我需要从方法返回一个列表。我的第一个实现不关心排序所以我这样做(复合是我的名为TreeSet):
composite.addAll(custom);
composite.addAll(reference);
Iterator<MyObject> anIter = composite.iterator();
ArrayList<MyObject> returnVal = new ArrayList<MyObject>();
while(anIter.hasNext())
returnVal.add(anIter.next());
执行此操作后,两个列表“custom”和“reference”将恢复为默认排序。 Javadocs for Collection的iterator()方法状态将以升序返回列表,这可能是我遇到麻烦的地方。
那么......是否有办法在保护原始列表排序的同时返回TreeSet的内容?我想到了一个树形集,因为我希望在两个集合上使用比较器接口的强大功能,将它们与addAll()结合起来,然后抛出欺骗。
有关保护订购的任何建议都将受到赞赏。
修改 的 *
Set<MyObject> composite = new TreeSet<MyObject>(new Comparator<MyObject>(){
@Override
public int compare(MyObject arg0, MyObject arg1) {
int arg0ID = arg0.getObjID();
int arg1ID = arg1.getObjID();
if(arg0ID < arg1ID) return -1;
else if(arg0ID> arg1ID) return 1;
else return 0;
}
});
答案 0 :(得分:3)
是否无法在保护原始列表排序的同时返回TreeSet的内容?
不,当然不是。 TreeSet
是这项工作的错误工具。使用TreeSet
的点是它对集合包含的对象应用基于Comparator
的排序。使用不同的数据结构 - LinkedHashSet
怎么样? - 如果要在保留插入顺序的同时删除重复的对象。
我不知道你的陈述如何反驳我的决定。我故意选择TreeSet,因为我想运用比较器接口。 ...我的比较器让我确定要过滤的对象的哪些组件。我不想失去这种能力
在TreeSet
:中“元素是按照自然顺序排序的,或者是在创建时创建时提供的比较器,具体取决于使用的构造函数。”你不能选择任何元素。订单排序(特别是像插入排序一样),TreeSet
。如果您无法使用equals()
和hashCode()
来选择代表身份的对象字段,请使用带有LinkedHashSet
的decorate-dedup-undecorate模式,其中装饰器包含equals()
}和hashCode()
实现。 Comparator
/ Comparable
用于指定排序,而不是标识或相等。
你建议我放弃它并转向像LinkedHashSet这样的东西吗?
是的,确切地说。要使MyObject
实现您所指的.equals()
和.hashCode()
:
class MyObject {
// snip
@Override
public boolean equals(Object o) {
// boilerplate junk here
if (!o instanceof MyObject) return false;
MyObject other = (MyObject) o;
return this.getObjID() == other.getObjID();
}
@Override
public int hashCode() {
return this.getObjID();
}
// snip
}
和重复数据删除如此:
List<MyObject> custom = /* snip */;
List<MyObject> reference = /* snip */;
Set<MyObject> uniques = new LinkedHashSet<>(custom.size() + reference.size());
uniques.addAll(custom);
uniques.addAll(reference);
List<MyObject> deduped = new ArrayList<>(uniques);
或者使用我提到的decorate-dedup-undecorate模式。装饰器类看起来像这样:
class Decorator {
private final MyObject value;
public Decorator(MyObject value) {
this.value = value;
}
public MyObject getValue() {
return value;
}
@Override
public boolean equals(Object o) {
// boilerplate junk here
if (!o instanceof Decorator) return false;
Decorator other = (Decorator) o;
return this.value.getObjID() == other.value.getObjID();
}
@Override
public int hashCode() {
return this.value.getObjID();
}
}
这里大概是你如何使用它:
List<MyObject> custom = /* snip */;
List<MyObject> reference = /* snip */;
Set<Decorator> uniques = new LinkedHashSet<>(custom.size() + reference.size());
for (MyObject m : custom) uniques.add(new Decorator(m));
for (MyObject m : reference) uniques.add(new Decorator(m));
List<MyObject> deduped = new ArrayList<>(uniques.size());
for (Decorator d : uniques) deduped.add(d.getValue());