【问题标题】:SubString gives OutOfMemory Exception when tried to give a very long string尝试给出很长的字符串时,SubString 给出 OutOfMemory 异常
【发布时间】:2019-08-07 02:17:01
【问题描述】:

我正在编写这段代码,以应对 leet 代码的编码挑战。

这段代码适用于 987 个测试用例中的 986 个。对于非常长的字符串(长度 ~ 31600)的情况,它会失败。 子字符串函数抛出 java.lang.OutOfMemoryError: Java heap space。

我已尝试创建“子字符串” new SubString(s.substring(i,j)); 和 s.substring(i,j).intern();在看到其他堆栈溢出的建议之后。但徒劳无功

private static Map<String, Integer> findAllSubStrings(String s) {
        Map<String, Integer> allSubStrings = new HashMap<>();
        for(int i = 0; i<s.length(); i++) {
            for(int j=i+1; j<=s.length(); j++) {
                String substring = s.substring(i,j);
                allSubStrings.put(substring, substring.length());
            }
        }
        return allSubStrings;
    }

例外是,

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.base/java.util.Arrays.copyOfRange(Arrays.java:4031)
at java.base/java.lang.StringLatin1.newString(StringLatin1.java:782)
at java.base/java.lang.String.substring(String.java:1888)
at main.LongestSubstring.findAllSubStrings(LongestSubstring.java:76)
at main.LongestSubstring.getLengthOfLongestSubString(LongestSubstring.java:44)
at main.LongestSubstring.main(LongestSubstring.java:38)

我正在寻找可以帮助我理解和解决此问题的人。

提前致谢。

【问题讨论】:

  • 挑战是否明确要求您返回Map&lt;String, Integer&gt;
  • 没有。我使用地图来存储子字符串。对于这么大的字符串,这肯定不适用。

标签: java string substring


【解决方案1】:

正如例外所说,您的空间不足了。

对于长度为n的字符串,有n(n-1)/2不同的子字符串要创建;当 n 大约为 32,000 时,这可以计算出大约 500 个 million 子字符串。每个String 对象至少占用 16 个字节的堆空间(但可能更多,甚至假设它们都共享相同的底层 char[],这样我们就不需要计算 内容 分开),所以你需要至少 8 GB 来代表它们。可能您的默认 Java 堆限制没有那么大。

您需要回到绘图板上,想出一个不依赖于内存中同时存在的所有子字符串的算法。

【讨论】:

  • ... 甚至假设它们都共享相同的底层 char[] - 对于最近的 JVM,它们没有。
  • @StephenC 感谢您的详细解释。我会尝试更有效地修改我的算法。
  • (阻止substring 共享后备数组的更改是在Java 8 中实现的。substring 方法now 创建一个新的char[],除了在退化可以返回this的情况。)
  • @StephenC:确实如此,但这只会让 OP 变得更糟。
【解决方案2】:

substring() 返回一个新字符串,它会消耗一些内存,存储所有子字符串最终会消耗所有堆。您需要在创建这些子字符串后立即consume(例如,将长度与最长长度进行比较),而不是将它们存储在集合中。

【讨论】:

  • 我在阅读您的评论后尝试了此解决方案。它帮助我摆脱了记忆异常。但是,我登陆的时间限制超出了异常。我想我必须按照@Henning Makholm 的建议重新设计我的代码。
猜你喜欢
  • 2023-03-22
  • 2011-12-06
  • 1970-01-01
  • 1970-01-01
  • 2017-10-02
  • 1970-01-01
  • 1970-01-01
  • 2021-10-06
  • 1970-01-01
相关资源
最近更新 更多