用完堆内存尝试在 Java 中将单个字符推送到堆栈

Posted

技术标签:

【中文标题】用完堆内存尝试在 Java 中将单个字符推送到堆栈【英文标题】:Running Out of Heap Memory Trying to Push a Single Character to Stack in Java 【发布时间】:2021-11-07 20:11:07 【问题描述】:

我正在尝试用 Java 为学校的表达式树程序制作一个中缀,为此我正在尝试实现一个后缀队列,该队列在传递一个中缀字符串后构造,在这个队列内部我使用的是 Java堆栈来保存运算符和分流场算法的左括号,表达式树必须使用通用节点来保存 char/int。

当我的程序尝试推送遇到的第一个 '(' 时,我遇到了堆内存错误

"Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.base/java.util.Arrays.copyOf(Arrays.java:3511)
    at java.base/java.util.Arrays.copyOf(Arrays.java:3480)
    at java.base/java.util.Vector.grow(Vector.java:262)
    at java.base/java.util.Vector.grow(Vector.java:266)
    at java.base/java.util.Vector.add(Vector.java:782)
    at java.base/java.util.Vector.addElement(Vector.java:617)
    at java.base/java.util.Stack.push(Stack.java:66)
    at project01/project1.PostfixQueue.<init>(PostfixQueue.java:128)
    at project01/project1.ExpressionTree.<init>(ExpressionTree.java:22)
    at project01/project1.Driver.main(Driver.java:11)"
    public PostfixQueue(String infix) 
    Stack<Character> opStack = new Stack<Character>();
    PostfixQueue postQueue = new PostfixQueue();
    
    
    Character digit;
    int numDigits = 0, result = 0;
    
    while(infix.length() > 0) 
        
        digit = (Character) infix.charAt(0);
        
        switch(digit) 
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
        case '0':
            if(numDigits > 0) 
                result = (result * 10) + Character.getNumericValue(digit); //if a result int is previously stored (multi digit int in the string)
                
                if(infix.charAt(1) >= 48 && infix.charAt(1) <= 57) 
                    numDigits++;
                    
                
                else 
                    //output result
                    postQueue.Enqueue(result);
                    
                    numDigits = 0; //reset numDigits
                
                
                
            
            else if(numDigits == 0) 
                if(infix.charAt(1) >= 48 && infix.charAt(1) <= 57)  //If next input is a number w/o whitespace (ex: 45)
                    numDigits++;
                    
                    result = Character.getNumericValue(digit);
                
                else 
                    numDigits = 0; //reset numDigits
                    
                    //output result
                    postQueue.Enqueue(result);
                
                
                
             //End else if
            break;
            
        case '+':
        case '-':
            if(opStack.empty() || opStack.peek() == '(')
            
                opStack.push(digit);
            
            else
                while(opStack.peek() == '+' || opStack.peek() == '-' || opStack.peek() == '*' || opStack.peek() == '/') 
                    //Pop operator and queue it
                    postQueue.Enqueue(opStack.pop());
                    
                // end while
            // end else
            opStack.push(digit);
            break;
        case '*':
        case '/':
            while(opStack.peek() == '*' || opStack.peek() == '/') 
                //Pop operator and queue it
                postQueue.Enqueue(opStack.pop());
            //end while
            opStack.push(digit);
            break;
        case '(':
            opStack.push(digit);
            break;
        case ')':
            while(opStack.peek() != '(') 
                //Pop operator and queue it
                postQueue.Enqueue(opStack.pop());
            // end while
            
            opStack.pop();
            
            break;
         // End Switch Statement           
        infix.substring(1);
        
     // End While Statement            
    this.first = postQueue.GetFirst();
     // End Constructor

'''

错误发生在“opStack.push(digit)”

顶部错误语句第 3511 行的变量是: copyOf() 抛出 OutOfMemoryError (id=20)

我该如何解决这个问题,以便我可以实际测试整个班级和其他班级的逻辑是否有效?

【问题讨论】:

PostfixQueue postQueue = new PostfixQueue(); 似乎是递归的。您正在构建一个PostfixQueue,这样做需要构建另一个。这可能是个问题。 @ElliottFrisch - 没有“可能” :-) @ElliottFrisch 我该如何解决这个问题?当我注释掉该行并尝试在没有它的情况下使用构造函数中的类方法时,我收到错误消息,指出“PostfixQueue 类型中的方法”Enqueue(T) 不适用于参数(字符)。在过去的几周里,我必须为这个项目学习 Java,它必须使用泛型,这不是我在课堂上或我所知道的语言中学到的概念 不要将所有逻辑都放在构造函数中。您没有为我们发布足够多的代码来真正提供超越一般性的帮助。同时,您发布了太多代码。在那里你抛弃了一个巨大的构造函数并称它足够好。 不知道除了我的非默认构造函数之外我还会把逻辑放在哪里,而且我还有一个默认构造函数,它的行“PostfixQueue postQueue = new PostfixQueue();”应该使用所以我仍然不确定它是如何开始递归的?而且错误发生在该行之后,错误发生在“case'(':opStack.push(digit);”的push语句中 【参考方案1】:

我发现了问题,我并没有意外更改循环条件,靠近底部的行 infix.substring(1); 应该是 infix = infix.substring(1);,我的程序试图创建一个无限的左括号堆栈。

【讨论】:

以上是关于用完堆内存尝试在 Java 中将单个字符推送到堆栈的主要内容,如果未能解决你的问题,请参考以下文章

在jQuery中将字符串推送到AJAX成功函数中的数组不起作用

pthread中将处理程序送到堆栈上

应用程序尝试在 didSelectRowAtIndexPath 中将 nil 视图控制器推送到目标上

如何在nodeJS的mysql查询中将值推送到数组?

如何在 MySQL 中将元素推送到 JSON

将视图推送到当前根视图下方的堆栈中