【问题标题】:how to solve Java heap space Exception for ArrayList Size?如何解决 ArrayList 大小的 Java 堆空间异常?
【发布时间】:2012-11-14 19:45:11
【问题描述】:

当我运行以下程序时,它显示给定数组的子集,其中数组大小为 19,则会引发 Java 堆空间异常。如何克服这个问题以获得数组大小> 19的子集?

import java.lang.*;
import java.util.*;
class def
{
    static List<List<Integer>> subset(int ele,List<List<Integer>>  w)
    {
        if(w.size()==0)
        {
            List<Integer> temp=new ArrayList<Integer>();
            temp.add(ele);
            w.add(temp);
        }
        else
        {
            int i,len=w.size();
            for(i=0;i<len;i++)
            {
                List<Integer> temp=new ArrayList<Integer>();
                for(Integer agh:w.get(i))
                {
                    temp.add(agh);
                }
                temp.add(ele);
                w.add(temp);
            }
            List<Integer> ghi=new ArrayList<Integer>();
            ghi.add(ele);
            w.add(ghi);
        }
        return w;
    }
    static void sub(int set[])
    {
        List<List<Integer>> ints = new ArrayList<List<Integer>>();
        int len=set.length,i;
        for(i=0;i<len;i++)
        {
            ints=subset(set[i],ints);
        }
        int count=0;
        for(List<Integer> temp:ints)
        {
            System.out.println("SET---"+count++);
            for(Integer agh:temp)
            {
                System.out.println(agh);
            }
        }

    }
    public static void main(String args[])
    {
        int a[]={3,4,9,14,15,19,28,37,47,50,54,56,59,61,70,73,78,81,92,95,97,99};
        sub(a); 
    }
}

这是一个例外: C:\Program Files (x86)\Java\jdk1.6.0_07\bin>javac def.java

C:\Program Files (x86)\Java\jdk1.6.0_07\bin>java def
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2760)
    at java.util.Arrays.copyOf(Arrays.java:2734)
    at java.util.ArrayList.ensureCapacity(ArrayList.java:167)
    at java.util.ArrayList.add(ArrayList.java:351)
    at def.subset(def.java:22)
    at def.sub(def.java:39)
    at def.main(def.java:55)

【问题讨论】:

  • 20 个元素的集合有 许多 个子集。
  • 为什么不只使用数组?!
  • 但据我所知,数组没有动态内存分配能力,而列表可以做到这一点。
  • 一种解决方案是不要一次存储所有子集,而是一次生成和处理一个。查看stackoverflow.com/questions/1670862/…的所有答案

标签: arrays multidimensional-array arraylist java


【解决方案1】:

您似乎创建了太多的 ArrayList 实例。您可以增加堆大小。但我认为您可以对代码进行一些小修改

else
    {
        int i,len=w.size();
        List<Integer> temp=new ArrayList<Integer>();   ///reuse this arraylist
        for(i=0;i<len;i++)
        {

            for(Integer agh:w.get(i))
            {
                temp.add(agh);
            }
            temp.add(ele);
            w.add(temp);
            temp.clear();
        }
        List<Integer> ghi=new ArrayList<Integer>();
        ghi.add(ele);
        w.add(ghi);
    }
    return w;

虽然这可能无法完全解决您的问题。但显然它会帮助垃圾收集器休息一下。 :D

【讨论】:

    【解决方案2】:

    您收到堆错误的原因是您正在创建数十亿个列表。 不要创建子列表,只是显示它们。

    public static void sub(int[] input){
        sub(new int[0],input);
    }
    
    public static void sub(int[] current, int[] remaining){
        System.out.println(Arrays.toString(current));
        int[] newCurrent = Arrays.copyOf(current, current.length+1);
    
        for(int i = 0;i < remaining.length;i++){
            newCurrent[newCurrent.length-1] = remaining[i];
            sub(newCurrent , Arrays.copyOfRange(remaining, i + 1, remaining.length));
        }
    
    }
    

    否则,您将需要一个比列表列表更智能的数据构造器。

    【讨论】:

    • 在我上面发布的代码 sn-p 中,我使用以前的子集列表来计算新的子集列表(即使显示也需要)。
    • 不,你不需要。如果你的递归方法正确,你所要做的就是提供一个前缀和一组剩余的数字。前缀始终最多为 n,余数集始终最多为 n。堆栈上仍有开销或数组可以减少。
    【解决方案3】:

    为了减少内存消耗,您可以将集合存储为位字段,例如带有元素 3, 9, 14 的集合将表示为 10110000000000000000 - 因此对于每个子集,您只需要一个 int

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-05
      • 1970-01-01
      • 2020-04-11
      • 1970-01-01
      • 2020-03-29
      • 1970-01-01
      • 2011-01-14
      • 2013-11-18
      相关资源
      最近更新 更多