【问题标题】:Stackoverflow at Arrays.asList(str.split(",")) -> due to wrong recursionArrays.asList(string.split(",")) 的堆栈溢出 -> 由于错误的递归
【发布时间】:2014-08-26 04:48:58
【问题描述】:

编辑: commaString 操作不是问题。这都是我的错。见下文。

我编写了一个将逗号字符串转换为字符串列表的方法。 但是我在这个方法中得到了一个stackoverflow。

Exception in thread "main" java.lang.StackOverflowError
at java.util.ArrayList.subList(Unknown Source)
at java.lang.String.split(Unknown Source)
at java.lang.String.split(Unknown Source)
at de.dhbw.horb.routePlanner.SupportMethods.commaStrToStrList(SupportMethods.java:82)

public static List<String> commaStrToStrList(String commaStr) {
    if (commaStr == null)
        return null;
    return new ArrayList<String>(Arrays.asList(commaStr.split(",")));
}

那么为什么会这样呢?我的 commaStr 大吗?如果是的话,还有什么可以用来做这个的?

doNextNode(id) 方法是一个递归。: https://github.com/Spenhouet/RoutenplanerProjekt/blob/master/Routenplaner/main/de/dhbw/horb/routePlanner/parser/JDomGraphDataCreator.java

编辑:

问题是由于我的递归方法中缺少子句。所以递归变得很深。起初我将我的最大堆栈大小推到 3GB (-Xss3g) 但它以内存不足异常结束。 :/

然后我想我的递归是否有可能从某一点重新开始,并一次又一次地做同样的事情。因此,我添加了一个地图,其中包含每个访问过的节点(id),并删除了失败的回收节点(回溯)。

现在它就像一个魅力。 感谢 Marco13 指出最终我的递归越来越深。

【问题讨论】:

  • 如果你的返回类型是List,为什么要把它放到一个新的ArrayList中呢?你不能直接返回Arrays.asList 吗?
  • @Rod_Algonquin 类似于以下内容:“第一、第二、第三、第四”
  • @besnep 就这样??而已??你能把整个字符串贴出来吗?
  • @MightyPork 我假设 OP 稍后会想要操作此列表,但您无法在列表中添加或删除元素,这将是 Arrays.asList 的结果。
  • StackOverflowError 并不必然意味着递归是无限的。这只意味着递归太深了。 100000 的递归深度将导致 SOE,即使它被限制在这个深度。可以重现问题的测试用例(最好是作为单个(!)复制+可粘贴代码块!)会有所帮助。否则:如果递归深度有限,您可以尝试从java -Xss2m YourApplication 开始将堆栈大小增加到2MB,看看这是否足够您的情况。

标签: java recursion stack-overflow backtracking


【解决方案1】:

如果您的字符串太大以至于String.split() 中断,您有以下选择:

  1. 试试StringTokenizer不太可能更好,但值得一试。更新:我检查了它的源代码,它看起来非常简单且节省内存,与选项 3 等效。
  2. 使用原始正则表达式 Matcher 并手动构建您的列表。
  3. 手动执行所有解析:遍历字符,如果遇到逗号,则使用最后一个逗号和当前逗号之间的字符创建一个字符串,并将其添加到列表中。

如果您仍然耗尽内存,则需要更复杂的方法,可能涉及将字符串写入文件并以较小的块读取。

【讨论】:

  • 嗯,看来我将不得不考虑其他解决方案。 java.util.StringTokenizer.scanToken(Unknown Source) 处 java.util.StringTokenizer.nextToken(Unknown Source) 处 java.lang.String.indexOf(Unknown Source) 处的线程“main”java.lang.StackOverflowError 异常...
  • 现在这很奇怪,因为StringTokenizer 绝对没有使用递归,调用堆栈深度不会取决于扫描字符串的长度。您确定在某处的调用代码中没有失控的递归吗?你能从堆栈跟踪中再显示几行吗?
  • @biziclop 据我所知,甚至不清楚 original 程序中是否涉及一些递归。当发布的方法处于深度递归调用的“底部”时,发生错误的实际基本上是随机的...
  • @Marco13 原始程序中涉及递归。链接到帖子中的 git 项目。
  • 我怀疑SOE是由于调用代码中的递归太深造成的,巧合的是,当您用完堆栈时,您恰好正在调用字符串拆分实现。跨度>
猜你喜欢
  • 2018-03-10
  • 2014-08-27
  • 2016-11-11
  • 2016-12-30
  • 2015-02-08
  • 1970-01-01
  • 1970-01-01
  • 2019-12-21
  • 2015-06-17
相关资源
最近更新 更多