【问题标题】:Java MergeSort - Out Of Memory Error: Java Heap SpaceJava MergeSort - 内存不足错误:Java 堆空间
【发布时间】:2013-03-22 20:36:06
【问题描述】:

我正在尝试使用 Java 进行排序。

我现在正在处理合并排序... Eclipse 正在输出Out Of Memory Error: Java Heap space,但我不确定如何调试它。

我觉得我的代码没问题 - 有什么想法吗?

import java.util.ArrayList;
import java.util.List;
public class Sorts {
    List<Integer> initialList;

    public Sorts() {
        initialList = new ArrayList<Integer>();
        initialList.add(2);
        initialList.add(5);
        initialList.add(9);
        initialList.add(3);
        initialList.add(6);

        System.out.print("List: [");
        for (int values : initialList) {
            System.out.print(values);
        }
        System.out.println("]");

        splitList(initialList);
    }

    public List<Integer> splitList(List<Integer> splitMe)   {
        List<Integer> left = new ArrayList<Integer>();
        List<Integer> right = new ArrayList<Integer>();

        if (splitMe.size() <= 1) {
            return splitMe;
        }

        int middle = splitMe.size()/2;
        int i = 0;
        for (int x: splitMe) {
            if (i < middle) {
                left.add(x);
            }
            else {
                right.add(x);
            }
            i++;
        }
        left = splitList(left);
        right = splitList(right);

        return mergeThem(left, right);
    }

    public List<Integer> mergeThem(List<Integer> left, List<Integer> right) {
        List<Integer> sortedList = new ArrayList<Integer>();
        int x = 0;
        while (left.size() > 0 || right.size() > 0) {
            if (left.size() > 0 && right.size() > 0) {
                if (left.get(x) > right.get(x)) 
                    sortedList.add(left.get(x));
                else 
                    sortedList.add(right.get(x));
            }
            else if (left.size() > 0) {
                sortedList.add(left.get(x));
            }
            else if (right.size() > 0) {
                sortedList.add(right.get(x));
            }
        }
        return sortedList;
    }   
}

【问题讨论】:

  • 我冒险猜测代码会无限地向列表中添加项目,直到没有更多内存为止。使用调试器逐步检查您的代码,看看是否正确。
  • 如果输入的 OOME 值那么小,则可能是无限递归。
  • 试试 visualvm.exe,它在 JDK 的 bin 文件夹中。谷歌教程。
  • 您的最后一个问题中描述了这些缺陷:stackoverflow.com/q/15563557/1065197。顺便说一句,错误出现在您的 mergeThem 方法中,您在该方法中无限期地在 sortedList 中添加元素。
  • 这是一种说删除左数组的第一个元素的方式,你没有做过。但不要试图完全按照算法进行操作,我建议您查看动画并获得自己的想法。

标签: java mergesort


【解决方案1】:

使用 Java 元素提供mergeThem 方法的可能实现:

public List<Integer> mergeThem(List<Integer> left, List<Integer> right) {
    //set the sorted list
    List<Integer> sortedList = new ArrayList<Integer>();
    //getting the iterators for both lists because List#get(x) can be O(N) on LinkedList
    Iterator<Integer> itLeft = left.iterator();
    Iterator<Integer> itRight = right.iterator();
    //getting flags in order to understand if the iterator moved
    boolean leftChange = true, rightChange = true;
    //getting the current element in each list
    Integer leftElement = null, rightElement = null;
    //while there are elements in both lists
    //this while loop will stop when one of the list will be fully read
    //so the elements in the other list (let's call it X) must be inserted
    while (itLeft.hasNext() && itRight.hasNext()) {
        //if left list element was added to sortedList, its iterator must advance one step
        if (leftChange) {
            leftElement = itLeft.next();
        }
        //if right list element was added to sortedList, its iterator must advance one step
        if (rightChange) {
            rightElement = itRight.next();
        }
        //cleaning the change flags
        leftChange = false;
        rightChange = false;
        //doing the comparison in order to know which element will be inserted in sortedList
        if (leftElement <= rightElement) {
            //if leftElement is added, activate its flag
            leftChange = true;
            sortedList.add(leftElement);
        } else {
            rightChange = true;
            sortedList.add(rightElement);
        }
    }
    //this is the hardest part to understand of this implementation
    //java.util.Iterator#next gives the current element and advance the iterator on one step
    //if you do itLeft.next then you lost an element of the list, that's why we have leftElement to keep the track of the current element of left list (similar for right list)
    if (leftChange && rightElement != null) {
        sortedList.add(rightElement);
    }
    if (rightChange && leftElement != null) {
        sortedList.add(leftElement);
    }
    //in the end, you should add the elements of the X list (see last while comments).
    while (itLeft.hasNext()) {
        sortedList.add(itLeft.next());
    }
    while (itRight.hasNext()) {
        sortedList.add(itRight.next());
    }
    return sortedList;
}

【讨论】:

    【解决方案2】:
    while (left.size() > 0 || right.size() > 0) {
    

    不会退出,因为您没有从左侧或右侧删除任何项目,因此您不断将项目添加到 sortedList 直到内存不足。您检查其中任何一个是否大于 0,但您永远不会删除任何项目,因此检查将永远不会返回 false,也就是无限循环。

    【讨论】:

    • 你也永远不会增加 x 这不是错误的原因。错误是 leftright 列表大小从不减小。
    • 我不应该增加 x 因为索引总是需要指向 0...列表中需要比较的第一个元素
    猜你喜欢
    • 2014-01-04
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    • 2019-10-09
    相关资源
    最近更新 更多