Find the union and intersection of linked list, given that elements don't repeat in a single linked list.
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));
}
}