I think the problem is the swap: you forgot to install the tail.
Here is a little test for this problem:
@Test public void test() { SwapListImpl<String> list = new SwapListImpl<String>(); list.add("A"); list.add("B"); list.add("C"); list.swap("A", "C"); assertEquals("C", list.get(0)); assertEquals("C", list.getHead().val); assertEquals("B", list.get(1)); assertEquals("A", list.get(2)); assertEquals("A", list.getTail().val); list.add("D"); assertEquals("C", list.get(0)); assertEquals("C", list.getHead().val); assertEquals("B", list.get(1)); assertEquals("A", list.get(2)); assertEquals("D", list.get(3)); assertEquals("D", list.getTail().val); list.swap("A", "C"); assertEquals("A", list.get(0)); assertEquals("A", list.getHead().val); assertEquals("B", list.get(1)); assertEquals("C", list.get(2)); assertEquals("D", list.get(3)); assertEquals("D", list.getTail().val); list.swap("C", "B"); assertEquals("A", list.get(0)); assertEquals("A", list.getHead().val); assertEquals("C", list.get(1)); assertEquals("B", list.get(2)); assertEquals("D", list.get(3)); assertEquals("D", list.getTail().val); }
You see that I added two methods to the list to get the head and tail, but it doesnβt matter - the test will even end without an explicit test for the head and tail. Additional methods for the list are very simple:
public Node<T> getTail() { return this.tail; } public Node<T> getHead() { return this.head; }
The problem of not setting the tail occurs when replacing the last element of the list, and then adding another element.
Here is a fixed version of the actual swap:
if (foundFirst && foundSecond) { if (second == this.tail) { this.tail = first; } else if (first == this.tail) { this.tail = second; } if (first == this.head) { this.head = second; } else if (second == this.head) { this.head = first; } if (firstPrev == second) { first.next = second; } else { if (firstPrev != null) { firstPrev.next = second; } first.next = secondNext; } if (secondPrev == first) { second.next = first; } else { if (secondPrev != first && secondPrev != null) { secondPrev.next = first; } second.next = firstNext; } break; }
You see that I did not add lines to your code, instead I wrote the code differently. I think this is more readable, but you can also try installing the tail correctly. But it was too complicated for me, so I reduced the complexity of this code - thatβs why I rewrote it.
I would suggest that you use the first and second for the first / second occurrence, and not for the first / second argument. I think this will improve the readability of the method. But this is another point; -)
I hope that helps - so the IMHO order is not a problem, but a tail.