我一直在尝试通过将子级分配给其父级然后通过it.remove()
以下方式将其删除来有效地创建树:
for (OgOrganizationTreeDTO parent : parents) {
setChildren(parent, organizationTree);
}
这是setChildren
功能的实现
private void setChildren(OgOrganizationTreeDTO root, List<OgOrganizationTreeDTO> allOrganizations) {
if (allOrganizations.isEmpty()) {
return ;
}
Iterator<OgOrganizationTreeDTO> it = allOrganizations.iterator();
while (it.hasNext()) {
OgOrganizationTreeDTO potentialChild = it.next();
if (potentialChild.getIdParentId() != null && potentialChild.getIdParentId().equals(root.getId())) {
root.addChild(potentialChild);
it.remove();
setChildren(potentialChild, allOrganizations);
}
}
}
我正在使用LinkedList并得到一个ConcurrentModificationException
。我已经通过将的副本传递allOrganizations
给递归setChildren
函数来解决了问题,例如new LinkedList<>(allOrganizations)
,但是副本部分需要O(n)
时间,我不希望这样。
我也尝试使用LinkedBlockingQueue
,但是发现删除需要O(n)
时间。
我想利用LinkedList
O(1)
remove的优势,因此每当我添加一个孩子并在其上重复出现时,列表就会变小。
我还成功实现了一个解决方案,方法HashSet
是将各个节点标记为可见,并将基本情况设置为hashSet.size() == allOrganizations.size()
,但是我仍然在相同大小的List上重复执行此操作,因此这对我没有任何帮助。
有什么方法可以实现我使用LinkedList
O(1)
remove的目标,或者有更有效的替代方法呢?
我不知道如何使用递归,因为您实际上在每个递归调用中都创建了一个新的迭代器(allOrganizations.iterator()-创建新的迭代器实例)。因此,当您调用delete时,您需要为其他迭代器修改集合,这就是为什么它将引发该异常的原因。
一种解决方案是使用一些CopyOnWriteList,它允许并发修改,但它只是传递列表的一个副本,而不是修改同一列表,因此将占用额外的内存。
另一种解决方案是在OgOrganizationTreeDTO类中添加一些属性,以标记该行是否已被处理。在这种情况下,您无需将其从列表中删除,只需将其标记为已处理即可。
但是无论如何,既然您在询问性能和大O,那么我可以为您提供另一个具有O(n)复杂度的解决方案。当然,需要在使用更多内存的情况下进行权衡,但这是标准内存与复杂性的问题...
private static void setChildrenMap(OgOrganizationTreeDTO root,
List<OgOrganizationTreeDTO> allOrganizations) {
Map<Integer, OgOrganizationTreeDTO> organizationsMap = new HashMap<>();
organizationsMap.put(root.getId(), root);
for (OgOrganizationTreeDTO element : allOrganizations) {
organizationsMap.put(element.getId(), element);
}
for (OgOrganizationTreeDTO element : allOrganizations) {
organizationsMap.get(element.getParentId()).addChild(element);
}
}
基本上,从哈希图中获取元素是恒定的时间,因此我们使用它来查找所需的父对象。如果期望元素包含错误的数据,则可能需要添加一些检查,因为organizationsMap.get(element.getParentId())
可能会返回null
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句