A complete Java Solution, using load factor, BST, Rehashing! Faster than 90%
```\n/This code has been written with the help of this Link:\nhttps://courses.cs.washington.edu/courses/cse373/13wi/lectures/02-11/HashSet.java\n/\nclass MyHash
```\n/*This code has been written with the help of this Link:\nhttps://courses.cs.washington.edu/courses/cse373/13wi/lectures/02-11/HashSet.java\n*/\nclass MyHashSet {\n    \n    BSTNode [] elements; //my elements are stored in binary trees!\n    int size;\n    final static double LOAD_FACTOR = 0.7;\n    final static int INITIAL_SIZE = 1; // 100 was picked totally random! No thoughts behind it.\n    \n    public MyHashSet() {\n        elements = (BSTNode[]) new BSTNode[INITIAL_SIZE];\n\t\tsize = 0;\n    }\n    \n    public void add(int key) {\n\t    int h = hash(key);\n\t    BSTNode newNode = new BSTNode(key);\n\t\tif(elements[h]==null){\n            elements[h]= newNode;\n        }\n        else{\n            elements[h].add(newNode);\n        }\n\t\tsize++;\n        if( size > (int)(LOAD_FACTOR*elements.length)){\n               rehash(); \n        }\n    }\n    public void remove(int key) { \n        //for more efficiency it does not call contains() before removing an item\n        //it rather checks if it exists while removing\n        int h=hash(key);\n        if(elements[h]!=null)\n            elements[h] = elements[h].remove(key);\n        size--;\n        \n    }\n    \n    /** Returns true if this set contains the specified element */\n    public boolean contains(int key) {\n        int h=hash(key);\n        if(elements[h]!=null)\n            return elements[h].contains(key);\n        return false;\n    }\n    \n     private int hash(int key){\n        return key % elements.length;\n    }\n    \n    private void rehash(){\n        BSTNode [] newElements = new BSTNode[elements.length*2];\n        BSTNode [] old = elements;\n        elements=newElements;\n        for(BSTNode n:old){\n            if(n!=null){\n                LinkedList <BSTNode> list = n.allTreeNodes(); \n                ListIterator it=list.listIterator();\n                while(it.hasNext()){\n                    BSTNode node = (BSTNode)it.next();\n                    add(node.data);\n                }\n            }\n        }   \n    }\n    \n    // Build in binary search tree node to take care of collisions, even long ones with ologn()\n    private class BSTNode {\n\t\tpublic int data;\n\t\tprivate BSTNode right;\n        private BSTNode left;\n\t\t\n\t\tprotected BSTNode(int data) {\n\t\t\tthis.data = data;\n\t\t}\n        \n        protected void add(BSTNode node){\n            //The add function is recursive, since there are as many as log(n) function calls\n            if(node.data>this.data){\n                if(this.right==null){\n                 this.right=node;   \n                }else{\n                    this.right.add(node);\n                }\n            }\n            else if(node.data<this.data){\n                if(this.left==null){\n                 this.left=node;   \n                }else{\n                    this.left.add(node);\n                }\n            }\n        }\n        \n        protected LinkedList<BSTNode> allTreeNodes(){ \n            // This function is iterative since there is n function calls,\n            //although the size of the stack can get as big as h~log(n)\n            // The reason linkedList is used here is that we just \n            //need to iterate over it once for rehashing!\n            Queue<BSTNode> q =new LinkedList<>();\n            q.add(this);\n            LinkedList <BSTNode> list=new LinkedList<>();\n            while(!q.isEmpty()){\n                BSTNode node=q.poll();\n                list.add(node);\n                if(node.right!=null)q.add(node.right);\n                if(node.left!=null)q.add(node.left);\n            }\n            return list;\n        }\n        \n        protected boolean contains(int data){\n            if(this.data==data)\n                return true;\n            if(this.data>data && this.left!=null)\n                return this.left.contains(data);\n            if(this.data<data && this.right!=null)\n                return this.right.contains(data);\n            return false;\n        }\n        \n        protected BSTNode remove(int d){\n            if(this.data==d){ //what we wanna remove is found\n                \n                if(this.right==null && this.left==null) //if leaf remove\n                    return null;\n                \n                if(this.right==null || this.left==null) //if one child return that one child!\n                    return (this.left!=null)?this.left:this.right;\n                \n                this.data=this.left.findMax().data; //substitude with the rightmost left successor\n                this.left.remove(this.data);\n            }\n            \n            if(this.data>d && this.left!=null)\n                this.left=this.left.remove(d);\n            \n            if(this.data<d && this.right!=null)\n                this.right=this.right.remove(d);\n            \n            return this;\n        }\n        \n        private BSTNode findMax(){\n            BSTNode node=this;\n            while(node.right!=null){\n                node=node.right;\n            }\n            return node;\n        }\n        \n\t}\n\n}\n\n/**\n * Your MyHashSet object will be instantiated and called as such:\n * MyHashSet obj = new MyHashSet();\n * obj.add(key);\n * obj.remove(key);\n * boolean param_3 = obj.contains(key);\n ["MyHashSet","add","add","contains","contains","add","contains","remove","contains"]\n[[],[1],[2],[1],[3],[2],[2],[2],[2]]\n \n \n */
[]