Find the union and intersection of linkedlist, given that elements dont repeat in a single linkedlist. This question is attributed to GeeksForGeeks. Looking for code-review, optimizations and best practices. public class IntersectionAndUnionLinkedList<T> { private Node<T> first; private Node<T> last; private int size; public IntersectionAndUnionLinkedList() {} public IntersectionAndUnionLinkedList(List<T> items ) { for (T item : items) { add (item); } } public void add(T item) { Node<T> node = new Node<T>(item); if (first == null) { first = last = node; } else { last.next = node; last = last.next; } size++; } private static class Node<T> { private T item; private Node<T> next; Node (T item) { this.item = item; } } public IntersectionAndUnionLinkedList<T> intersection(IntersectionAndUnionLinkedList<T> list) { final Set<T> items = new HashSet<>(); Node<T> smallerListNode; Node<T> largerListNode; if (list.size < size) { smallerListNode = list.first; largerListNode = first; } else { smallerListNode = first; largerListNode = list.first; } while (smallerListNode != null) { items.add(smallerListNode.item); smallerListNode = smallerListNode.next; } IntersectionAndUnionLinkedList<T> intersectionlist = new IntersectionAndUnionLinkedList<>(); while (largerListNode != null && items.size() > 0) { if (items.contains(largerListNode.item)) { intersectionlist.add(largerListNode.item); items.remove(largerListNode.item); } largerListNode = largerListNode.next; } return intersectionlist; } public IntersectionAndUnionLinkedList<T> union(IntersectionAndUnionLinkedList<T> list) { final Set<T> items = new HashSet<>(); Node<T> smallerListNode; Node<T> largerListNode; if (list.size < size) { smallerListNode = list.first; largerListNode = first; } else { smallerListNode = first; largerListNode = list.first; } IntersectionAndUnionLinkedList<T> intersectionlist = new IntersectionAndUnionLinkedList<>(); while (smallerListNode != null) { items.add(smallerListNode.item); intersectionlist.add(smallerListNode.item); smallerListNode = smallerListNode.next; } while (largerListNode != null) { if (!items.contains(largerListNode.item)) { intersectionlist.add(largerListNode.item); } largerListNode = largerListNode.next; } return intersectionlist; } // size of new linkedlist is unknown to us, in such a case simply return the list rather than an array. public List<T> toList() { List<T> list = new ArrayList<>(); if (first == null) return list; for (Node<T> x = first; x != null; x = x.next) { list.add(x.item); } return list; } @Override public int hashCode() { int hashCode = 1; for (Node x = first; x != null; x = x.next) hashCode = 31*hashCode + (x == null ? 0 : x.hashCode()); return hashCode; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; IntersectionAndUnionLinkedList<T> other = (IntersectionAndUnionLinkedList) obj; Node<T> currentListNode = first; Node<T> otherListNode = other.first; while (currentListNode != null && otherListNode != null) { if (currentListNode.item != otherListNode.item) return false; currentListNode = currentListNode.next; otherListNode = otherListNode.next; } return currentListNode == null && otherListNode == null; } } public class IntersectionAndUnionLLTest { @Test public void intersection() { IntersectionAndUnionLinkedList<Integer> ll1 = new IntersectionAndUnionLinkedList<>(Arrays.asList(1, 2, 3, 4, 5)); IntersectionAndUnionLinkedList<Integer> ll2 = new IntersectionAndUnionLinkedList<>(Arrays.asList(3, 4, 5, 6, 7)); IntersectionAndUnionLinkedList<Integer> llExpected1 = new IntersectionAndUnionLinkedList<>(Arrays.asList(3, 4, 5)); assertEquals(llExpected1, ll1.intersection(ll2)); } @Test public void union() { IntersectionAndUnionLinkedList<Integer> ll1 = new IntersectionAndUnionLinkedList<>(Arrays.asList(1, 2, 3, 4, 5)); IntersectionAndUnionLinkedList<Integer> ll2 = new IntersectionAndUnionLinkedList<>(Arrays.asList(3, 4, 5, 6, 7)); IntersectionAndUnionLinkedList<Integer> llExpected2 = new IntersectionAndUnionLinkedList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7)); assertEquals(llExpected2, ll1.union(ll2)); } @Test public void intersectionNull() { IntersectionAndUnionLinkedList<Integer> ll1 = new IntersectionAndUnionLinkedList<>(Arrays.asList(1, 2, 3, 4, 5)); IntersectionAndUnionLinkedList<Integer> ll3 = new IntersectionAndUnionLinkedList<>(); IntersectionAndUnionLinkedList<Integer> llExpected3 = new IntersectionAndUnionLinkedList<>(); assertEquals(llExpected3, ll1.intersection(ll3)); } @Test public void unionNull() { IntersectionAndUnionLinkedList<Integer> ll1 = new IntersectionAndUnionLinkedList<>(Arrays.asList(1, 2, 3, 4, 5)); IntersectionAndUnionLinkedList<Integer> ll4 = new IntersectionAndUnionLinkedList<>(); IntersectionAndUnionLinkedList<Integer> llExpected4 = new IntersectionAndUnionLinkedList<>(Arrays.asList(1, 2, 3, 4, 5)); assertEquals(llExpected4, ll1.union(ll4)); } }