Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most efficient way to prevent an infinite recursion in toString()?

To string on a collection can get into a infinite loop if somewhere in the graph of collected items is a reference back to itself. See example below.

Yes, good coding practices should prevent this in the first place, but anyway, my question is: What is the most efficient way to detect a recursion in this situation?

One approach is to use a set in a threadlocal, but that seems a bit heavy.

public class AntiRecusionList<E> extends ArrayList<E> {
  @Override
  public String toString() {
    if (  /* ???? test if "this" has been seen before */ ) {
        return "{skipping recursion}";
    } else {
        return super.toString();
    }
  }
}


public class AntiRecusionListTest {
  @Test
  public void testToString() throws Exception {
      AntiRecusionList<AntiRecusionList> list1 = new AntiRecusionList<>();
      AntiRecusionList<AntiRecusionList> list2 = new AntiRecusionList<>();
      list2.add(list1);
      list1.add(list2);
      list1.toString();  //BOOM !
  }
}
like image 975
marathon Avatar asked Jul 02 '12 19:07

marathon


People also ask

How do you stop infinite recursion?

To prevent infinite recursion, you need at least one branch (i.e. of an if/else statement) that does not make a recursive call. Branches without recursive calls are called base cases; branches with recursive calls are called recursive cases. Functions can also be mutually recursive.

How do you stop a recursive loop?

To avoid recursive triggers you can create a class with a static Boolean variable with default value true. In the trigger, before executing your code keep a check that the variable is true or not. Once you check make the variable false.

What causes infinite recursion?

Infinite Recursion occurs when the recursion does not terminate after a finite number of recursive calls. As the base condition is never met, the recursion carries on infinitely.

What will happen what happens when infinite recursion occurs?

This case—when the function completes without making a recursive call—is called the base case. If a recursion never reaches a base case, it will go on making recursive calls forever and the program will never terminate. This is known as infinite recursion, and it is generally not considered a good idea.


1 Answers

When I have to iterate over risky graphs, I usually make a function with a decrementing counter.

For example :

public String toString(int dec) {
    if (  dec<=0 ) {
        return "{skipping recursion}";
    } else {
        return super.toString(dec-1);
    }
}

public String toString() {
    return toString(100);
}

I won't insist on it, as you already know it, but that doesn't respect the contract of toString() which has to be short and predictable.

like image 161
Denys Séguret Avatar answered Sep 20 '22 18:09

Denys Séguret