我正在尝试编写一个递归方法,该方法搜索IData对象列表并返回特定实现。该列表包含实现接口IData的对象。
此接口有两种实现方式:
1)DataImpl
2)DataContainerImpl
DataContainerImpl有一个:
List<IData> children;
所以它可以保存嵌套的DataContainerImpl元素或只是普通的DataImpl。这是我的工作:
public static DataContainerImpl findDataContainerWithName(Collection<IData> elements, String name) {
for (IData element : elements) {
if (element instanceof DataContainerImpl) {
DataContainerImpl container = (DataContainerImpl) element;
if (container.getName().equals(name)) {
return container ;
}
container = findDataContainerWithName(container.getChildren(), name);
if (container != null) {
return container ;
}
}
}
return null;
}
答案 0 :(得分:5)
不完全确定你在这里做了什么,但是在它前面没有“返回”的情况下递归调用“findContainerByName()”对你没什么好处。
递归调用将返回,但随后调用将下降到底部并返回null。
例如,如果您的列表只包含1个DataContainerImpl,其名称与您调用方法的名称不匹配,但它包含一个只包含1个DataImpl的列表,您仍然会返回null。这是你想要的吗?
答案 1 :(得分:4)
坚持原始循环来处理列表,只有在找到DataContainerImpl时才会递归。
public static DataContainerImpl findDataContainerWithName(Collection<IData> elements, String name) {
for (IData element : elements) {
if (element instanceof DataContainerImpl) {
DataContainerImpl container = (DataContainerImpl) element;
if (container.getName().equals(name)) {
return container;
}
container = findDataContainerWithName(container.getChildren(), name);
if (container) {
return container;
}
}
}
return null;
}
答案 2 :(得分:1)
我认为问题的根本原因在于您通过递归搜索列表中的相同元素。即这里
// Call with remaining list...
Collection<IData> copyAll = EcoreUtil.copyAll(elements);
copyAll.remove(count);
findDataContainerWithName(copyAll, name);
使用原始列表调用减去当前元素,而不仅仅是当前元素后的元素。因此,递归调用将不必要地一遍又一遍地检查相同的元素。特别是当你每次循环遍历列表时,这将是一个纯粹的递归方法是不必要的。
因此,如果您绝对想要使此搜索递归,则应仅检查第一个元素,然后将其从列表中删除,并使用其余列表递归调用。或者,如果您更喜欢在列表上循环,则在常见情况下(当元素不是DataContainerImpl
时)不需要任何递归。这将是Java的做事方式,因为Java - 与函数式语言不同 - 对递归的支持有限。
答案 3 :(得分:1)
除了答案中已经提到的问题之外,您正在对列表中的每个元素进行递归调用,并传入所有其他元素。
因此,对于长度为N的列表,您将递归N-deep(不必要),从每个递归级别的列表中弹出一个元素。但是所有这些元素都可以在同一级别处理。
你是人为增加递归深度,因此你的StackOverflowError问题