Find all nodes in tree, without a sibling Find all nodes of trees, without siblings.


This question is attributed to GeeksForGeeks.

I'm looking for code reviews, optimizations and best practices.

  public class PrintNodesWithoutSiblings&lt;T&gt; {

        private TreeNode&lt;T&gt; root;

        public PrintNodesWithoutSiblings(List&lt;T&gt; items) { 
            create(items);
        }

        private void create (List&lt;T&gt; items) {
            root = new TreeNode&lt;T&gt;(items.get(0));

            final Queue&lt;TreeNode&lt;T&gt;&gt; queue = new LinkedList&lt;TreeNode&lt;T&gt;&gt;();
            queue.add(root);

            final int half = items.size() / 2;

            for (int i = 0; i &lt; half; i++) {
                if (items.get(i) != null) {
                    final TreeNode&lt;T&gt; current = queue.poll();
                    int left = 2 * i + 1;
                    int right = 2 * i + 2;

                    if (items.get(left) != null) {
                        current.left = new TreeNode&lt;T&gt;(items.get(left));
                        queue.add(current.left);
                    }
                    if (right &lt; items.size() &amp;&amp; items.get(right) != null) {
                        current.right = new TreeNode&lt;T&gt;(items.get(right));
                        queue.add(current.right);
                    }
                }
            }
        }

        private static class TreeNode&lt;T&gt; {
            private TreeNode&lt;T&gt; left;
            private T item;
            private TreeNode&lt;T&gt; right;

            TreeNode(T item) {
                this.item = item;
            }
        }


        public List&lt;T&gt; nonSiblingNodes() {
            if (root == null) {
                throw new IllegalStateException("Empty tree. Tree cannot be empty.");
            }

            final List&lt;T&gt; list = new ArrayList&lt;T&gt;();
            findNonSiblingNodes(root, list);
            return list;
        } 


        private void findNonSiblingNodes(TreeNode&lt;T&gt; node, List&lt;T&gt; list) {
            if (node == null) {
                return;
            }

            if (node.left != null &amp;&amp; node.right != null) {
                findNonSiblingNodes(node.left, list);
                findNonSiblingNodes(node.right, list);
            } else if (node.left != null) {
                list.add(node.left.item);
                findNonSiblingNodes(node.left, list);
            } else if (node.right != null) {
                list.add(node.right.item);
                findNonSiblingNodes(node.right, list);
            }
        }
    }


    public class PrintNodesWithoutSiblingTest {


        @Test
        public void test1() {
            PrintNodesWithoutSiblings&lt;Integer&gt; ps1 = new PrintNodesWithoutSiblings&lt;Integer&gt;(Arrays.asList(1, 2, 3, 4, null, 6, null));
            assertTrue(Arrays.asList(4, 6).equals(ps1.nonSiblingNodes()));
        }

        @Test
        public void test2() {
            PrintNodesWithoutSiblings&lt;Integer&gt; ps2 = new PrintNodesWithoutSiblings&lt;Integer&gt;(Arrays.asList(1, 2, null, 4, null, null, null));
            assertTrue(Arrays.asList(2, 4).equals(ps2.nonSiblingNodes()));
        }
    }
Recursion
The null-check in your recursive method is redundant. The preliminary checks and the mid-recursion checks ensure that the method is never called with a null input.
I also really favour a simplified recursive approach, where the recursion checks it's own conditions, instead of pre-checking the recursive conditions before calling the recursion. In this case, it halves the number of recursive calls, halves the list.adds, and reduces by a third the number of if-conditions in your code:
    private void findNonSiblingNodes(TreeNode&lt;T&gt; node, boolean hasSibling List&lt;T&gt; list) {
        if (node == null) {
            return;
        }

        if (!hasSibling) {
            list.add(node);
        }

        findNonSiblingNodes(node.left, node.right != null, list);
        findNonSiblingNodes(node.right, node.left != null, list);
    }

You would call that code with:
    public List&lt;T&gt; nonSiblingNodes() {
        final List&lt;T&gt; list = new ArrayList&lt;T&gt;();
        findNonSiblingNodes(root, true, list);
        return list;
    } 
}

It is safe to remove the null-check on the root node, because it can never be null at that point. That's because ....
Bugs
... your code does horrible things in the constructor, which will fail before it gets here:
    public PrintNodesWithoutSiblings(List&lt;T&gt; items) { 
        create(items);
    }

    private void create (List&lt;T&gt; items) {
        root = new TreeNode&lt;T&gt;(items.get(0));
        ....

Your constructor will throw NPE if the items is null, and will throw NoSuchElementException if the List is empty. Thus, the root will never be null in the recursion.
Style

final Queue&lt;TreeNode&lt;T&gt;&gt; queue = new LinkedList&lt;TreeNode&lt;T&gt;&gt;();


You should use the 'diamond operator' when using Java7 and later. The line above can be just:
final Queue&lt;TreeNode&lt;T&gt;&gt; queue = new LinkedList&lt;&gt;();

Similarly, the line:

final List&lt;T&gt; list = new ArrayList&lt;T&gt;();


can be:
final List&lt;T&gt; list = new ArrayList&lt;&gt;();