0

对不起,我没有找到更好的标题:-)

我有一个树结构,这是我的“节点”类:

public class Categoria implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    private String name;

    @OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
    @JoinColumn(name = "parent_id")
    private List<Categoria> children = new LinkedList<Categoria>();

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(
        name = "parent_id",
        insertable=false,
        updatable=false
    )
    private Categoria parent;

    @Transient
    private Integer depth;

    private Integer orderNumber;

... getters, setters, ....
}

不用关心 Hibernate/JPA 注释,它们没有问题,只要想一个理想的 pojo 世界。

我做了一个递归方法,它建立了一个“普通”的相邻节点列表。所以,想象一下这棵树:

grandfather

 |_ father

    |_ son1

    |_ son2

 |_ uncle

grandmother

 |_ mother

我们将得到一个这样的列表(数字是“深度”):-祖父(1)-父亲(2)-儿子1(3)-儿子2(3)-叔叔(2)-祖母(1)-母亲( 2)

所有这些都很好。

现在我想让我的用户编辑节点排序(在相同深度节点之间),我的意思是:如果我想要上面列表中的“son1”之前的“son2”怎么办?

所以我要添加一个“orderNumber”属性:所有 orderNumbers 最初都是 0。然后我的用户将son1的orderNumber设置为99,将son2的orderNumber设置为88。

问题是:如何重新排列结果列表以根据 orderNumber 进行排序?

但是等等....我只想对“子列表”进行排序,所以儿子排序绝对与“父亲”和“叔叔”排序无关!

谢谢你帮助我们。

编辑:你们都错过了一件事。我没有很好地解释自己。这是一个例子:

  • 祖父(深度:1,订单号:1)
  • 父亲(深度:2,订单号:1)
  • 儿子1(深度:3,订单号:1)
  • 儿子2(深度:3,订单号:2)
  • 叔叔(深度:2,订单号:2)
  • 祖母(深度:1,订单号:2)
  • 母亲(深度:2,订单号:1)

现在我想交换son1和son2,所以结果列表将是:

  • 祖父(深度:1,订单号:1)
  • 父亲(深度:2,订单号:1)
  • 儿子2(深度:3,订单号:1)
  • 儿子1(深度:3,订单号:2)
  • 叔叔(深度:2,订单号:2)
  • 祖母(深度:1,订单号:2)
  • 母亲(深度:2,订单号:1)

我怎样才能为此目的实现 sort / compareTo ?

4

4 回答 4

2

让 Categoria 实现Comparable。创建一个自定义 compareTo 实现,您可以在其中按深度排序,并根据您的附加 OrderNumber 属性决定。这适用于任何可排序的集合。

但是根据您使用该树结构解决的问题,为您的树实现自定义迭代器而不是递归创建“列表快照”可能更合适?

于 2012-06-08T10:06:59.020 回答
1

您可以使用 Collections.sort() 和适当的比较器对子列表进行显式排序。

如果在创建列表时知道排序,则可以使用带有比较器而不是 LinkedList 的有序集(如 TreeSet)。因此,插入时将对项目进行排序。

于 2012-06-08T10:08:27.880 回答
1

我会让你的类实现Comparable,并且在compareTo方法中我会使用字段depthorderNumber计算顺序。完成此操作后,您可以使用 Collectoins.sort() 对列表进行排序。

示例代码:

public class Categoria implements Serializable, Comparable<Categoria> {

    private static final long serialVersionUID = 1L;

    // ... omitting other fields/annotations/getters/setters

    private Integer depth;

    private Integer orderNumber;

    @Override
    public int compareTo(Categoria other) {
        if (depth < other.depth)
            return -1;
        if (depth > other.depth)
            return 1;
        // if we get here the two objects have the same depth, so we compare 
        // based on orderNumber
        if (orderNumber < other.orderNumber)
            return -1;
        if (orderNumber > other.orderNumber)
            return 1;
        return 0;
    }

}
于 2012-06-08T12:59:47.033 回答
0

我需要那个:

private List<Categoria> getAlberoCategorie(Categoria root, int profondita) {
        List<Categoria> tmpList = new ArrayList<Categoria>();
        root.setProfondita(profondita);
        if ( root.getParent() != null ) {
            Hibernate.initialize(root.getTraduzioni());
            tmpList.add(root);
        }       

        List<Categoria> children = root.getChildren();
        Collections.sort(children, new Comparator<Categoria>() {
            @Override
            public int compare(Categoria o1, Categoria o2) {
                return o1.getOrdinamento().compareTo(o2.getOrdinamento());
            }
        });

        if (!children.isEmpty()) {
            profondita++;
            for (Categoria figlia : children) {
                List<Categoria> discendenza = getAlberoCategorie(figlia,profondita);                
                tmpList.addAll(discendenza);
            }
        }       
        return tmpList;
    }

总之谢谢大家!

于 2012-06-11T06:56:27.930 回答