abstract class Tree { public abstract boolean contains((A, A) -> boolean less, A x); public abstract Tree insert ((A, A) -> boolean less, A x); } class EmptyTree extends Tree { public boolean contains((A, A) -> boolean less, A x) { return false; } public Tree insert((A, A) -> boolean less, A x) { return new Branch(x, this, this); } } class Branch extends Tree { A elem; Tree left; Tree right; public Branch(A elem, Tree left, Tree right) { this.elem = elem; this.left = left; this.right = right; } public boolean contains((A, A) -> boolean less, A x) { if (less(x, elem)) return left.contains(less, x); else if (less(elem, x)) return right.contains(less, x); else // we assume total ordering, therefore x.equals(elem) return true; } public Tree insert((A, A) -> boolean less, A x) { if (less(x, elem)) return new Branch(elem, left.insert(less, x), right); else if (less(elem, x)) return new Branch(elem, left, right.insert(less, x)); else return this; } } class StringBranch extends Branch { StringBranch(String elem, Tree left, Tree right) { super(elem, left, right); } private static boolean stringLess(String x, String y) { return x.compareTo(y) > 0; } public boolean contains(String x) { return contains(stringLess, x); } public Tree insert(String x) { return insert(stringLess, x); } }