java - TreeSet 到 List 转换中的 Controller 排序

标签 java sorting collections tree

我的方法中有 2 个列表按特定顺序排序(根据 ID 字段升序或降序)

我有一个自定义比较器实现,它允许我将两个列表放入树集中并实现所需的结果。

我的问题是加载树集后,我需要从该方法返回一个列表。我的第一个实现并不关心排序,所以我这样做了(复合是我命名的 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());

执行此操作后,“自定义”和“引用”两个列表将恢复默认顺序。 Collection 的 iterator() 方法的 Javadocs 声明将按升序返回列表,这可能是我的麻烦所在。

那么...有没有办法在保护原始列表顺序的同时返回 TreeSet 的内容?我想到了树集,因为我想在两个集合上使用比较器接口(interface)的强大功能,将它们与 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;
        }           
    }); 

最佳答案

is there no way to return the content of a TreeSet while protecting the original list ordering?

不,当然不是。 TreeSet 是不适合这项工作的工具。使用TreeSet要点是它对集合包含的对象应用基于Comparator的排序。使用不同的数据结构 - LinkedHashSet 怎么样? ? — 如果您想在保留插入顺序的同时删除重复的对象。


I don't see how your statement refutes my decision. I intentionally CHOSE the TreeSet because I wanted to exercise the comparator interface. ... My comparator let me identify what components of the object to filter on. I don't want to lose that capability

TreeSet中:“元素使用其自然顺序进行排序,或者通过在设置创建时提供的比较器进行排序,具体取决于使用的构造函数。”您不能选择任何顺序(特别是像插入顺序这样的顺序):一个TreeSet。如果您无法使用 equals()hashCode() 来选择表示身份的对象字段,请使用带有 LinkedHashSet 的decorate-dedup-undecorate 模式,其中装饰器包含 equals()hashCode() 实现。 Comparator/Comparable 用于指定顺序,而不是同一性或相等性。


You're suggesting I need to abandon it and move to something like 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());

关于java - TreeSet 到 List 转换中的 Controller 排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12466326/

相关文章:

java - 为什么 Collections.shuffle(List) 之后会出现空行?

java - Java servlet 类需要什么 Action 变量?

javadoc "@author"没有显示?

java - XY 图 : Annotation is placed incorrectly with respect to Y axis

android - 如何使用嵌套属性对 RealmList 对象进行排序?

java - 如何合并几个列表?

java - 编译为 Jar 文件后找不到类

php - 如何使用 arsort() 在 PHP 中进行稳定排序?

java - 时髦的冒泡排序 (Java Eclipse)

java - 如果指定仅包含两个元素的数组列表的容量,是否有任何性能/内存优势?