我想问一个关于 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;
}
如果当前的元组是另一个元组的子组,则基本上告诉它反转顺序,反之亦然,但列表仍然不是我期望的那样。
关于如何使用流来做到这一点的任何想法?我不想使用需要递归的复杂排序方法,只是为了保持代码更清晰,但如果无法完成,我会检查一下。
谢谢!
编辑:我将添加一些信息:
您已经提到元组是唯一的。因此该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] 删除。
我来说两句