对相互链接的连音列表进行排序

丹尼尔·帕瓦内利

我想问一个关于 Java 排序的问题,准确地说,我需要对一个元组列表(定义为自定义类)进行排序,但它们像树一样相互链接。

基本上,这是一个表示父子关系的文档 ID 列表,并组织为集合(可能是无序的)。元组已经被过滤为具有唯一的左/右元素,因此树在文档之间具有唯一的链接(它们不允许有多个叶子)。

使用示例数据,我有这样的列表:[(1,2), (3,4), (0,1), (2,3)],这代表以下树:

0
|_ 1
   |_ 2
      |_ 3
         |_ 4

因此,我需要订购如下列表:[(0,1), (1,2), (2,3), (3,4)]

我还补充说,父文档 id 可能大于子文档 id,因此基于哪个 id 更大的简单排序是不可能的。

.sorted()在使自定义类具有可比性并添加以下代码后,我尝试使用Stream 类方法:

    @Override
    public int compareTo(DocumentIdVersionsStack o) {
        if (parentDocumentId == o.getChildDocumentId()) return  1;
        if (childDocumentId == o.getParentDocumentId()) return  -1;
        return 0;
    }

如果当前的元组是另一个元组的子组,则基本上告诉它反转顺序,反之亦然,但列表仍然不是我期望的那样。

关于如何使用流来做到这一点的任何想法?我不想使用需要递归的复杂排序方法,只是为了保持代码更清晰,但如果无法完成,我会检查一下。

谢谢!

编辑:我将添加一些信息:

  • 元组已经是连续的,不会有丢失 id 的“漏洞”
  • 在将元组传递给排序方法之前再次注意递归(最后一个 id = 第一个 id)
  • 将有一个元组,其左值在任何右值中都找不到 -> 这将是排序后的第一个元素
  • 将有一个元组,在任何左值中都找不到正确的值 -> 这将是排序后的最后一个元素
  • 所有 left 和 right 值都是唯一的,它们只是像之前解释的那样链接(left1 = right2 等等)
高瑟姆

您已经提到元组是唯一的。因此该compareTo方法将不起作用,因为它也处理“相等”元素,这不适用于唯一列表。在当前compareTo代码中,元组 (1,2) 和 (3,4) 将被视为相等,这就是它不返回预期结果的原因。此外,由于父 ID 可能大于子 ID,因此您无法清楚地说 (1,2) 是大于还是小于 (3,4)。顺序可以是(1,2), (2,3), (3,4)(3,4), (4,1), (1,2)因此,在不知道其他节点的详细信息的情况下,可能无法使用compareTo.

我会建议一种方法来保留这些元组的映射,以父 ID 作为键,然后找到根节点并从根开始遍历:

Map<Integer, DocumentIdVersionsStack> map = list.stream()//
                .collect(Collectors.toMap(DocumentIdVersionsStack::getParentId,
                                          Function.identity()));

Set<Integer> child = list.stream()
                         .map(DocumentIdVersionsStack::getChildId)
                         .collect(Collectors.toSet());


// Get the root node
DocumentIdVersionsStack node = list.stream()
                                   .filter(u -> !child.contains(u.getParentId()))
                                   .findFirst()
                                   .orElse(null);
List<DocumentIdVersionsStack> list2 = new ArrayList<>();
list2.add(node);
// Traverse using the map
while (map.containsKey(node.getChildId())) {
    node = map.get(node.getChildId());
    list2.add(node);
}
System.out.println(list2);

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章