This is more a question that I would like to tell than a question: when printing using toString() Java detects direct loops in the collection (where the collection refers to itself), but not indirect loops (where the collection refers to another collection that refers to first, or with a lot of steps).
import java.util.*; public class ShonkyCycle { static public void main(String[] args) { List a = new LinkedList(); a.add(a);
This was real for me, because in the debugging code to print the collection (I was surprised when I saw a direct loop, since I realized that they generally performed the check in general). The question arises: why?
The explanation I can think of is that it’s very inexpensive to check a collection that references itself, since you need to store the collection (which you already have), but for longer cycles you need to save all the collections with which you collide starting at the root. In addition, you may not be able to say exactly what the root is, and therefore you will need to store each collection in the system, which you do anyway, but you will also need to do a hash search for each element of the collection. This is very expensive for a relatively rare case of cycles (in most programs). (I think), the only reason he checks for direct loops is because it is so cheap (one comparative comparison).
OK ... I somehow answered my question - but did I miss something important? Anyone want to add something?
Clarification: I now understand that the problem I saw is specific to printing the collection (i.e. the toString() method). There are no problems with loops per se (I use them myself and need them); the problem is that Java cannot print them. Edit Andrzej Doyle points to not only collections, but also any object that is called toString .
Given that it is limited to this method, here is an algorithm for checking it:
- root is the object to which the first
toString() is called (in order to determine this, you need to maintain a state of whether toString is now or not, so this is inconvenient).- when you cross each object, you add it to IdentityHashMap along with a unique identifier (for example, an index with an extension).
- but if this object is already on the map, write down its identifier.
This approach also correctly displays multirefs (a node that is mentioned more than once).
The cost of memory is IdentityHashMap (one link and index per object); complexity cost is a hash search for each node in a directed graph (i.e. each printed object).
13ren source share