递归获取StackOverFlow错误(Java.lang.StackOverFlowError)

时间:2019-06-13 01:12:24

标签: java recursion junit junit4 hashset

我正在努力通过以下代码和测试用例。但是由于从Link.java文件进行递归调用而导致堆栈溢出错误。

我已经尝试增加JVM的堆栈大小,这是堆栈溢出中的一些提示所建议的,但这无济于事。

有人可以给我一些解决方案来解决LinkTest.java文件中的所有测试用例吗?

Link.java


public class Link {
    private HashSet<Link> links = new HashSet<Link>();

    public void linkTo(Link link) {
        links.add(link);
    }

    public Boolean isLinkedTo(Link to) {
        Link link;

        while (!links.isEmpty()) {
            link = links.iterator().next();


            if (link == to || link.isLinkedTo(to) == true) {
                if (link == to) {
                    return true;
                } else if (link != to && link.isLinkedTo(to) == true) {
                    return true;
                } else if (link != to && link.isLinkedTo(to) == false) {
                    return false;
                } else {
                    return true;
                }
            } else if (link != to || link.isLinkedTo(to) == false) {
                if (link == to) {
                    return true;
                } else if (link.isLinkedTo(to) == true) {
                    return true;
                } else {
                    return false;
                }
            } else {
                return true;
            }
        }


        return false;
    }
}

LinkTest.java

public class LinkTest extends TestCase
{
    @org.junit.Test
    public void testItCanLinkToItself()
    {
        Link foo = new Link();
        foo.linkTo(foo);
        assertTrue(foo.isLinkedTo(foo));
    }

    public void testItDoesNotLinkToItself()
    {
        Link foo = new Link();
        assertFalse(foo.isLinkedTo(foo));
    }


    public void testUnidirectionalLinkToNeighbour()
    {
        Link foo = new Link();
        Link bar = new Link();
        bar.linkTo(foo);
        assertTrue(bar.isLinkedTo(foo));
        assertFalse(foo.isLinkedTo(bar));
    }

    public void testNeighboursWithConnectionsToThemselves()
    {
        Link foo = new Link();
        Link bar = new Link();
        Link baz = new Link();

        // Connect the Objs to themselves.
        foo.linkTo(foo);
        bar.linkTo(bar);
        baz.linkTo(baz);

        // Connect baz => bar => foo.
        baz.linkTo(bar);
        bar.linkTo(foo);



        assertTrue(baz.isLinkedTo(foo));
        assertTrue(baz.isLinkedTo(bar));
        assertTrue(bar.isLinkedTo(foo));
        assertFalse(bar.isLinkedTo(baz));
    }

    public void testCyclicGraph()
    {
        Link foo = new Link();
        Link bar = new Link();
        Link baz = new Link();

        // Connect the nodes baz => bar => foo => baz.
        baz.linkTo(bar);
        bar.linkTo(foo);
        foo.linkTo(baz);

        assertTrue(baz.isLinkedTo(foo));
        assertTrue(baz.isLinkedTo(bar));
        assertTrue(baz.isLinkedTo(baz));
    }

    public void testItCanHaveNeighboursInCyclicGraph()
    {
        Link foo = new Link();
        Link bar = new Link();
        Link baz = new Link();

        // Connect the nodes baz => bar <=> foo.
        baz.linkTo(bar);
        bar.linkTo(foo);
        foo.linkTo(bar);

        assertTrue(baz.isLinkedTo(foo));
        assertTrue(baz.isLinkedTo(bar));
        assertFalse(baz.isLinkedTo(baz));

    }

    public void testCanHaveACycleOfMoreThanTwo()
    {
        Link foo = new Link();
        Link bar = new Link();
        Link baz = new Link();
        Link qux = new Link();

        // Connect the nodes baz => bar => foo => qux => bar.
        baz.linkTo(bar);
        bar.linkTo(foo);
        foo.linkTo(qux);
        qux.linkTo(bar);

       assertFalse(qux.isLinkedTo(baz));
        assertTrue(baz.isLinkedTo(foo));
        assertTrue(baz.isLinkedTo(bar));
        assertTrue(baz.isLinkedTo(qux));
       assertFalse(baz.isLinkedTo(baz));

    }

}

1 个答案:

答案 0 :(得分:0)

我相信这将如您的测试所述。

public boolean isLinkedTo(Link to) {
    // start recursion with no currently checked links
    return isLinkedTo(to, new HashSet<>());
}

private boolean isLinkedTo(Link to, Set<Link> linksChecked) {
    // this link is linked to 'to'
    if (links.contains(to)) {
        return true;
    }
    // this link not linked to 'to' so add it to the checked links
    linksChecked.add(this);
    // check all links to see if the links are linked to 'to'
    for (Link link: links) {
        // current link not checked yet and current link is linked to 'to'
        if (!linksChecked.contains(link) && link.isLinkedTo(to, linksChecked)) {
            return true;
        }
    }
    // no links or sub-links are linked to 'to'
    return false;
}

要递归地检查自链接链接而没有无限递归,则必须跟踪已检查的链接,以避免无限地检查相同的链接。这就是为什么我添加了一个辅助方法来跟踪选中的链接的原因。

正如Elliott的上面的评论所述,当使用对象的哈希集时,您想要覆盖类的equals和hashcode方法以确保哈希集按预期工作。多数情况下,仅作为附注,大多数ide都可以自动为您的类生成有效的equals哈希码。