我有一个程序,它生成数字组合的排列。排列具有给定的大小(在本例中为6)。我的问题是,我得到了一个java.lang.OutOfMemoryError: Java堆空间错误,它具有更大的数字组合。例如,如果我从18个数字中计算出置换,就会得到这样的异常:
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
at javax.swing.text.GapContent.allocateArray(Unknown Source)
at javax.swing.text.GapVector.resize(Unknown Source)
at javax.swing.text.GapVector.shiftEnd(Unknown Source)
at javax.swing.text.GapContent.shiftEnd(Unknown Source)
at javax.swing.text.GapVector.open(Unknown Source)
at javax.swing.text.GapVector.replace(Unknown Source)
at javax.swing.text.GapContent.insertString(Unknown Source)
at javax.swing.text.AbstractDocument.handleInsertString(Unknown Source)
at javax.swing.text.AbstractDocument.insertString(Unknown Source)
at javax.swing.text.PlainDocument.insertString(Unknown Source)
at javax.swing.JTextArea.append(Unknown Source)
at test.permute(test.java:48)
at test.permute(test.java:52)
at test.permute(test.java:52)
at test.permute(test.java:52)
at test.permute(test.java:52)
at test.permute(test.java:52)
at test.permute(test.java:52)
at test.actionPerformed(test.java:74)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)现在看来,这似乎是由打印出JTextArea中的排列引起的,因为如果您查看异常的第一行,就可以在javax.swing.text上看到错误。
下面是我使用的代码:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
public class test extends JFrame implements ActionListener {
private JPanel panel;
private JButton ok;
private JTextArea text;
private String str;
private JScrollPane scroll;
public test() {
panel = new JPanel();
ok = new JButton("OK");
ok.addActionListener(this);
str = ("1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, ");
text = new JTextArea(str, 16, 16);
text.setEditable(true);
scroll = new JScrollPane(text);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
panel.add(scroll);
panel.add(ok);
add(panel);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new test();
}
//-----------------------------------------------------------------------------------
public void permute(java.util.List<Integer> intList, int k, int max) {
if(k == max) {
text.append(Arrays.toString(intList.subList(0, max).toArray()).replaceAll( "\\[|\\]", "") + ", \n");
} else {
for(int i = k; i < intList.size(); i++){
java.util.Collections.swap(intList, i, k);
permute(intList, k+1, max);
java.util.Collections.swap(intList, k, i);
}
}
}
//-----------------------------------------------------------------------------------
@Override
public void actionPerformed(ActionEvent arg0) {
String a = text.getText();
text.setText("");
String[] zahlenstring = a.split(", ");
int[] zahlenint = new int[zahlenstring.length];
for(int i = 0; i < zahlenstring.length ;i++) {
zahlenint[i] = Integer.parseInt(zahlenstring[i]); }
ArrayList<Integer> intList = new ArrayList<Integer>();
for (int i = 0; i < zahlenint.length; i++) {
intList.add(zahlenint[i]); }
permute(intList, 0, 6);
}
}我寻找解决方案,但我主要找到了将ram添加到java或使用多线程的建议,这两者我都不想在这里使用。
现在我的问题是:我如何改进这段代码,这样它就不会再让我感到恶心了?这里还有什么需要改进的吗?
如果你还有问题,你可以在评论中问。提前谢谢。
发布于 2015-08-13 19:10:29
与其构建一个使用非常大(或不切实际)内存量的字符串,你需要处理每一个被确定的排列。
public static void permute(List<Integer> intList, Consumer<List<Integer>> permutationConsumer) {
permute(intList, 0, intList.size(), permutationConsumer);
}
public static void permute(List<Integer> intList, int k, int max, Consumer<List<Integer>> permutationConsumer) {
if(k == max) {
permutationConsumer.accept(intList.subList(0, max));
return;
}
for(int i = k; i < intList.size(); i++) {
Collections.swap(intList, i, k);
permute(intList, k + 1, max, permutationConsumer);
Collections.swap(intList, k, i);
}
}此解决方案将不再使用任何内存。
若要显示此结果,请执行以下操作
permute(intList, System.out::println);这不会在显示前生成一个大字符串,因此不会耗尽内存。
发布于 2015-08-15 18:58:03
当您处理大量的元素时,最好提前计算它们将消耗多少内存。
你的排列会消耗掉

字节,假设每个组合消耗12个字节。因此,消耗的内存总量将在160 of左右。此内存量仅用于将组合存储为字符串。当您将它们添加到TextArea中时,至少需要加倍所需的内存量。
解决内存问题的最简单方法是,一旦计算出排列,就输出它。您可以将其写入控制台或文件。在这种情况下,您将不需要任何额外的内存。
但是,如果您的唯一选择是创建GUI应用程序,那么您可以执行以下操作。首先,您需要认识到至少(13366080 * k)字节用于排列字符串(其中k是每个置换字符串的大小),13366080 * 16字节用于存储字符串数组和一些额外的内存以使应用程序平稳运行(防止GC暂停)。如果我的计算是正确的,它将是大约500 my的堆内存。
接下来,不应该将字符串直接添加到TextArea中。相反,创建排列的ArrayList<String>,创建ScrollBar,用结果数组的大小初始化它。在ScrollBar的位置变化上,用ScrollBar位置的元素重新初始化TextArea (从滚动条的位置取少量的元素,并将它们作为行添加到TextArea中)。
https://stackoverflow.com/questions/31994246
复制相似问题