{"id":82,"date":"2009-01-30T23:02:57","date_gmt":"2009-01-31T06:02:57","guid":{"rendered":"http:\/\/www.connorgarvey.com\/blog\/?p=82"},"modified":"2010-02-12T09:23:32","modified_gmt":"2010-02-12T16:23:32","slug":"a-recursive-tostring-method-for-trees","status":"publish","type":"post","link":"https:\/\/connorgarvey.com\/blog\/?p=82","title":{"rendered":"A recursive toString method for trees"},"content":{"rendered":"<p>While working on a project that uses Hibernate, my team was getting a little frustrated while trying to interrogate a tree structure in our data model since all collections are mapped as java.util.HashSets.\u00a0 We wanted a simple function that could print the tree to the log, so I took a free hour and wrote this.\u00a0 It was a little more complicated than I anticipated because it had to handle situations like these.<\/p>\n<pre>root\r\n   |\r\n   |- child\r\n   |\r\n   |- child\r\n\r\nroot\r\n   |\r\n   |- child\r\n      |\r\n      |- child<\/pre>\n<p>and the infamous (to me) &#8230;<\/p>\n<pre>root\r\n   |\r\n   |- child\r\n   |   |\r\n   |   |- child\r\n   |       |\r\n   |       |- child\r\n   |\r\n   |- child<\/pre>\n<p>There&#8217;s a subtle difference.\u00a0 Notice that in the middle one, the line for the first child stops because there aren&#8217;t any more children, but in the last one, the line continues?\u00a0 I could have created some kind of 2D text buffer and gone back to draw the line, but that would be boring.\u00a0 Here&#8217;s what I came up with.  I don&#8217;t know whether it&#8217;s pretty, but it works!<\/p>\n<div id=\"wpshdo_1\" class=\"wp-synhighlighter-outer\"><div id=\"wpshdt_1\" class=\"wp-synhighlighter-expanded\"><table border=\"0\" width=\"100%\"><tr><td align=\"left\" width=\"80%\"><a name=\"#codesyntax_1\"><\/a><a id=\"wpshat_1\" class=\"wp-synhighlighter-title\" href=\"#codesyntax_1\"  onClick=\"javascript:wpsh_toggleBlock(1)\" title=\"Click to show\/hide code block\">Code block<\/a><\/td><td align=\"right\"><a href=\"#codesyntax_1\" onClick=\"javascript:wpsh_code(1)\" title=\"Show code only\"><img decoding=\"async\" border=\"0\" style=\"border: 0 none\" src=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/themes\/default\/images\/code.png\" \/><\/a>&nbsp;<a href=\"#codesyntax_1\" onClick=\"javascript:wpsh_print(1)\" title=\"Print code\"><img decoding=\"async\" border=\"0\" style=\"border: 0 none\" src=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/themes\/default\/images\/printer.png\" \/><\/a>&nbsp;<a href=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/About.html\" target=\"_blank\" title=\"Show plugin information\"><img decoding=\"async\" border=\"0\" style=\"border: 0 none\" src=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/themes\/default\/images\/info.gif\" \/><\/a>&nbsp;<\/td><\/tr><\/table><\/div><div id=\"wpshdi_1\" class=\"wp-synhighlighter-inner\" style=\"display: block;\"><pre class=\"java\" style=\"font-family:monospace;\"><span class=\"co3\">\/**\n * Creates a tree representation of the node\n * @param node The node, which may not be null\n * @return A string containing the formatted tree\n *\/<\/span>\n<span class=\"kw1\">public<\/span> <span class=\"kw1\">static<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky\"><span class=\"kw3\">String<\/span><\/a> toStringTree<span class=\"br0\">&#40;<\/span>Node node<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n  <span class=\"kw1\">final<\/span> StringBuilder buffer <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> StringBuilder<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n  <span class=\"kw1\">return<\/span> toStringTreeHelper<span class=\"br0\">&#40;<\/span>node, buffer, <span class=\"kw1\">new<\/span> LinkedList<span class=\"sy0\">&lt;<\/span>Iterator<span class=\"sy0\">&lt;<\/span>Node<span class=\"sy0\">&gt;&gt;<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"me1\">toString<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n<span class=\"br0\">&#125;<\/span>\n&nbsp;\n<span class=\"kw1\">private<\/span> <span class=\"kw1\">static<\/span> <span class=\"kw4\">void<\/span> toStringTreeDrawLines<span class=\"br0\">&#40;<\/span>List<span class=\"sy0\">&lt;<\/span>Iterator<span class=\"sy0\">&lt;<\/span>Node<span class=\"sy0\">&gt;&gt;<\/span> parentIterators, <span class=\"kw4\">boolean<\/span> amLast<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n  StringBuilder result <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> StringBuilder<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n  Iterator<span class=\"sy0\">&lt;<\/span>Iterator<span class=\"sy0\">&lt;<\/span>Node<span class=\"sy0\">&gt;&gt;<\/span> it <span class=\"sy0\">=<\/span> parentIterators.<span class=\"me1\">iterator<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n  <span class=\"kw1\">while<\/span> <span class=\"br0\">&#40;<\/span>it.<span class=\"me1\">hasNext<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n    Iterator<span class=\"sy0\">&lt;<\/span>Node<span class=\"sy0\">&gt;<\/span> anIt <span class=\"sy0\">=<\/span> it.<span class=\"me1\">next<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n    <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>anIt.<span class=\"me1\">hasNext<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">||<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>it.<span class=\"me1\">hasNext<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">&amp;&amp;<\/span> amLast<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n      result.<span class=\"me1\">append<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;   |&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n    <span class=\"br0\">&#125;<\/span>\n    <span class=\"kw1\">else<\/span> <span class=\"br0\">&#123;<\/span>\n      result.<span class=\"me1\">append<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;    &quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n    <span class=\"br0\">&#125;<\/span>\n  <span class=\"br0\">&#125;<\/span>\n  <span class=\"kw1\">return<\/span> result.<span class=\"me1\">toString<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n<span class=\"br0\">&#125;<\/span>\n&nbsp;\n<span class=\"kw1\">private<\/span> <span class=\"kw1\">static<\/span> StringBuilder toStringTreeHelper<span class=\"br0\">&#40;<\/span>Node node, StringBuilder buffer, List<span class=\"sy0\">&lt;<\/span>Iterator<span class=\"sy0\">&lt;<\/span>Node<span class=\"sy0\">&gt;&gt;<\/span>\n    parentIterators<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n  <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>parentIterators.<span class=\"me1\">isEmpty<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n    <span class=\"kw4\">boolean<\/span> amLast <span class=\"sy0\">=<\/span> <span class=\"sy0\">!<\/span>parentIterators.<span class=\"me1\">get<\/span><span class=\"br0\">&#40;<\/span>parentIterators.<span class=\"me1\">size<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">-<\/span> 1<span class=\"br0\">&#41;<\/span>.<span class=\"me1\">hasNext<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n    buffer.<span class=\"me1\">append<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;<span class=\"es0\">\\n<\/span>&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n    <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky\"><span class=\"kw3\">String<\/span><\/a> lines <span class=\"sy0\">=<\/span> toStringTreeDrawLines<span class=\"br0\">&#40;<\/span>parentIterators, amLast<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n    buffer.<span class=\"me1\">append<\/span><span class=\"br0\">&#40;<\/span>lines<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n    buffer.<span class=\"me1\">append<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;<span class=\"es0\">\\n<\/span>&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n    buffer.<span class=\"me1\">append<\/span><span class=\"br0\">&#40;<\/span>lines<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n    buffer.<span class=\"me1\">append<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;- &quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n  <span class=\"br0\">&#125;<\/span>\n  buffer.<span class=\"me1\">append<\/span><span class=\"br0\">&#40;<\/span>node.<span class=\"me1\">toString<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n  <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>node.<span class=\"me1\">hasChildren<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n    Iterator<span class=\"sy0\">&lt;<\/span>Node<span class=\"sy0\">&gt;<\/span> it <span class=\"sy0\">=<\/span> node.<span class=\"me1\">getChildNodes<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"me1\">iterator<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n    parentIterators.<span class=\"me1\">add<\/span><span class=\"br0\">&#40;<\/span>it<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n    <span class=\"kw1\">while<\/span> <span class=\"br0\">&#40;<\/span>it.<span class=\"me1\">hasNext<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n      Node child <span class=\"sy0\">=<\/span> it.<span class=\"me1\">next<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n      toStringTreeHelper<span class=\"br0\">&#40;<\/span>child, buffer, parentIterators<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n    <span class=\"br0\">&#125;<\/span>\n    parentIterators.<span class=\"me1\">remove<\/span><span class=\"br0\">&#40;<\/span>it<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n  <span class=\"br0\">&#125;<\/span>\n  <span class=\"kw1\">return<\/span> buffer<span class=\"sy0\">;<\/span>\n<span class=\"br0\">&#125;<\/span><\/pre><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>While working on a project that uses Hibernate, my team was getting a little frustrated while trying to interrogate a tree structure in our data model since all collections are mapped as java.util.HashSets.\u00a0 We wanted a simple function that could print the tree to the log, so I took a free hour and wrote this.\u00a0 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[59],"tags":[4,22,7,21],"class_list":["post-82","post","type-post","status-publish","format-standard","hentry","category-java","tag-java","tag-recursive","tag-redpoint","tag-tree"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1ql2n-1k","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/82","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=82"}],"version-history":[{"count":13,"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/82\/revisions"}],"predecessor-version":[{"id":84,"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/82\/revisions\/84"}],"wp:attachment":[{"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=82"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=82"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=82"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}