Java 在递归通用数据结构中对对象进行排序

Java 在递归通用数据结构中对对象进行排序,java,sorting,generics,tree,Java,Sorting,Generics,Tree,我有一个通用树类,其中每个树节点都保存一些数据。每段数据都有一个字符串类型的属性。我想按此属性按字母顺序对每个树节点的子节点进行排序 树类: public class Tree<T>{ public T data; public List<Tree<T>> children = new ArrayList<Tree<T>>(); } 我的想法是使用sort()方法扩展Tree类,并使用类似于以下的比较器,但我仍停留在比

我有一个通用树类,其中每个树节点都保存一些数据。每段数据都有一个字符串类型的属性。我想按此属性按字母顺序对每个树节点的子节点进行排序

树类:

public class Tree<T>{
    public T data;
    public List<Tree<T>> children = new ArrayList<Tree<T>>();
}
我的想法是使用sort()方法扩展Tree类,并使用类似于以下的比较器,但我仍停留在比较函数上:

public class Tree<T>{
    public T data;
    public List<Tree<T>> children = new ArrayList<Tree<T>>();

    public void sort(){
        Collections.sort(this.children,
            new Comparator<Tree<T>>(){
                @Override
                public int compare(Tree<T> objectA, Tree<T> objectB){
                    //I am stuck here!
                    return 0;
                }
            }
        );
        for(Tree<T> child: this.children){
            child.sort();
        }
    }
}
公共类树{
公共数据;
public List children=new ArrayList();
公共无效排序(){
Collections.sort(this.children,
新比较器(){
@凌驾
公共int比较(树对象A、树对象B){
//我被困在这里了!
返回0;
}
}
);
for(树形子:this.children){
child.sort();
}
}
}
我有不同的想法来解决这个问题:

  • 使用反射来访问对象的属性并进行比较
  • 在DataItem中实现可比较的接口
  • 使用新接口访问对象的属性以进行比较:

    public interface GetComparisonAttribute {
        public String getComparisonAttribute();
    }
    
    public class DataItem implements GetComparisonAttribute{
        public String name;
    
        @Override
        public String GetComparisonAttribute(){
            return this.name;
        }
    }
    
    //the comparison function inside Tree<T>.sort():
    public int compare(Tree<T> objectA, Tree<T> objectB){
        return objectA.data.getComparisonAttribute()
            .compareToIgnoreCase(objectB.data.getComparisonAttribute());
    }
    
    公共接口GetComparisonAttribute{
    公共字符串getComparisonAttribute();
    }
    公共类DataItem实现GetComparisonAttribute{
    公共字符串名称;
    @凌驾
    公共字符串GetComparisonAttribute(){
    返回此.name;
    }
    }
    //Tree.sort()中的比较函数:
    公共int比较(树对象A、树对象B){
    返回objectA.data.getComparisonAttribute()
    .compareToIgnoreCase(objectB.data.GetComparIsonaAttribute());
    }
    
什么是正确的或最好的做法?还有别的办法吗

能够指定排序属性可能很重要

我认为直接在树上使用Collections.sort()会很好,但在这种递归数据结构中实现它确实让我感到困惑。这样做的一个缺点是我无法指定排序属性。

尝试以下方法:

public class Tree<T> {
    public T data;
    public List<Tree<T>> children = new ArrayList<Tree<T>>();
    private Class<T> type;

    public Tree(Class<T> t) {
        type = t;
    }

    public void sort(){
        Collections.sort(this.children,
            new Comparator<Tree<T>>(){
                @Override
                public int compare(Tree<T> objectA, Tree<T> objectB){
                if (type==DataItem.class)
                   {
                    DataItem diA = (DataItem) (objectA.data);
                    DataItem diB = (DataItem) (objectB.data);

                    return diA.name.compareTo(diB.name);
                    }
                  else
                    throw new IllegalArgumentException();

                }
            }
        );
        for(Tree<T> child: this.children){
            child.sort();
        }
    }

}
公共类树{
公共数据;
public List children=new ArrayList();
私人阶级类型;
公树(t类){
类型=t;
}
公共无效排序(){
Collections.sort(this.children,
新比较器(){
@凌驾
公共int比较(树对象A、树对象B){
if(type==DataItem.class)
{
数据项直径=(数据项)(objectA.data);
DataItem diB=(DataItem)(objectB.data);
返回diA.name.compareTo(diB.name);
}
其他的
抛出新的IllegalArgumentException();
}
}
);
for(树形子:this.children){
child.sort();
}
}
}

创建类树时,应该传递它的类型T。然后,您可以向下转换到
DataItem
,并根据您喜欢的字段对列表进行排序。当然,除了
DataItem
之外,您还可以对照其他类型参数进行检查

publicsvoid排序(最后,我只浏览了一下您的代码,因此我可能遗漏了一些明显的内容,但是您的数据结构做了什么,使您不能将您的
子项
保留在
SortedSet
中?我在这里提供的数据结构只是一个很小的示例。它有很多用于遍历的方法和其他奇特的东西,但它们是We’对于这个问题来说并不重要。通用数据结构对我来说是一个有趣的话题,所以我希望它能起作用。我不认为SortedSet或TreeSet可以在每个节点中存储数据,但只能在其叶子中存储。将子节点保留在SortedSet中并不能真正解决问题。为了实现这个目标,树必须实现Compariable,但比较取决于树的数据属性。嗯,现在我只想将数据结构定义为“Tree extensed Comparable”解决了部分问题,但它仍然不允许我动态指定T的排序属性。如果希望在
树中允许该特定类型的参数,为什么不为类型参数添加边界-
T extends DataItem
?在这种情况下,您将能够访问
DataItem
@R的属性ohitJain树必须处理任意类型的对象!我认为这是不够的。如果我想将树与其他类型一起使用,我必须更改树的代码!如果你不想与其他数据类型排序,那么它就足够了,当你尝试对它们排序时,它将抛出异常。如果你想排序,你应该这样做其他数据类型的sort()方法中的相同过程我查看了您的解决方案,我很喜欢!它确实帮助了我解决了这个问题!我想这就是我一直在寻找的!
    public void sort(final Comparator<? super T> dataComparator)
    {
        Collections.sort(this.children,
            new Comparator<Tree<T>>()
            {
                @Override
                public int compare(Tree<T> treeA, Tree<T> treeB)
                {
                    return dataComparator.compare(treeA.getData(), treeB.getData());
                }
            }
        );
        for(Tree<T> child: this.children)
        {
            child.sort(dataComparator);
        }
    }


void test()
{
    Tree<DataItem> tree = new Tree<>();

    tree.sort(new Comparator<DataItem>()
    {
        @Override
        public int compare(DataItem dataA, DataItem dataB)
        {
            return dataA.getName().compareTo(dataB.getName());
        }
    });

}
    public void sort(final Comparator<? super T> dataComparator)
    {
        Collections.sort(this.children,
            new Comparator<Tree<T>>()
            {
                @Override
                public int compare(Tree<T> treeA, Tree<T> treeB)
                {
                    return dataComparator.compare(treeA.getData(), treeB.getData());
                }
            }
        );
        for(Tree<T> child: this.children)
        {
            child.sort(dataComparator);
        }
    }


void test()
{
    Tree<DataItem> tree = new Tree<>();

    tree.sort(new Comparator<DataItem>()
    {
        @Override
        public int compare(DataItem dataA, DataItem dataB)
        {
            return dataA.getName().compareTo(dataB.getName());
        }
    });

}
    public void sort(final Comparator<? super T> dataComparator)
    {
        Collections.sort(this.children, 
            Comparator.comparing(Tree::getData, dataComparator));

        for(Tree<T> child: this.children)
        {
            child.sort(dataComparator);
        }
    }


void test()
{
    Tree<DataItem> tree = new Tree<>();

    tree.sort( Comparator.comparing(DataItem::getName) );
}