patternjavaMinor
Java Singly Linked List
Viewed 0 times
singlylistlinkedjava
Problem
Here is a naive version of a singly linked list in Java. It implements only
SinglyLinkedList.java:
```
package com.ciaoshen.thinkinjava.newchapter17;
import java.util.*;
public class SinglyLinkedList implements Collection, Iterable {
private int size = 0;
private Node head = new Node();
// constructor
public SinglyLinkedList() {
head.setNext(head);
}
public SinglyLinkedList(Collection c) {
this();
addAll(c);
}
// unmodifiable collection (except remove() method)
public Iterator iterator() {
return new Iterator() {
Node cursor = head;
Node previous = head;
public boolean hasNext() {
return cursor.getNext() != head;
}
public E next() {
if (! hasNext()) {
throw new IndexOutOfBoundsException("Iterator has reached the end of the list!");
}
Node toReturn = cursor.getNext();
previous = cursor;
cursor = toReturn;
return toReturn.getInfo();
}
public void remove() { // only remove once the last node return by next() method.
if (cursor == previous) {
throw new IndexOutOfBoundsException("Cannot remove current node. Last node returned by next() already removed, or reach the head of the list!");
}
previous.setNext(cursor.getNext());
cursor.setNext(null);
cursor = previous;
size--;
}
};
}
public int size() {
return size;
}
public String toString() {
if (isEmpty()) {
return "[]";
}
StringBuilder sb = new StringBuilder();
Iterator ite = iterator();
sb.append("[");
while (ite.hasNext()) {
sb.app
Collection and Iterable interfaces. Any comments and suggestions are welcome.SinglyLinkedList.java:
```
package com.ciaoshen.thinkinjava.newchapter17;
import java.util.*;
public class SinglyLinkedList implements Collection, Iterable {
private int size = 0;
private Node head = new Node();
// constructor
public SinglyLinkedList() {
head.setNext(head);
}
public SinglyLinkedList(Collection c) {
this();
addAll(c);
}
// unmodifiable collection (except remove() method)
public Iterator iterator() {
return new Iterator() {
Node cursor = head;
Node previous = head;
public boolean hasNext() {
return cursor.getNext() != head;
}
public E next() {
if (! hasNext()) {
throw new IndexOutOfBoundsException("Iterator has reached the end of the list!");
}
Node toReturn = cursor.getNext();
previous = cursor;
cursor = toReturn;
return toReturn.getInfo();
}
public void remove() { // only remove once the last node return by next() method.
if (cursor == previous) {
throw new IndexOutOfBoundsException("Cannot remove current node. Last node returned by next() already removed, or reach the head of the list!");
}
previous.setNext(cursor.getNext());
cursor.setNext(null);
cursor = previous;
size--;
}
};
}
public int size() {
return size;
}
public String toString() {
if (isEmpty()) {
return "[]";
}
StringBuilder sb = new StringBuilder();
Iterator ite = iterator();
sb.append("[");
while (ite.hasNext()) {
sb.app
Solution
Advice 1
I would declare
Advice 2
In
By default, Java sets reference members to
Advice 3
Name
Advice 4
You can write the above more succintly:
Advice 5
Integer fields are initialized to zero by default; write only
Advice 6
Use diamond inference:
Advice 7
The correct exception is
Advice 8
The correct exception here is
Advice 9
Your
Advice 10
What??? If lists are equal in type and size you conclude that they are equal if they have same hash code? Unfortunately, there is a small chance that two different lists have same hash value, so do not rely on it. Instead, you could do:
Advice 11
Hope that helps.
I would declare
Node as the static private inner class in SinglyLinkedList:public class SinglyLinkedList ... {
...
private static final class Node {
...Advice 2
In
Node you haveprivate T info = null;By default, Java sets reference members to
null by default, so that you can write simplyprivate T info;Advice 3
Name
info is not the best possible; consider using data or datum.Advice 4
public int hashCode() {
if (info == null) {
return 0;
}
return info.hashCode();
}You can write the above more succintly:
public int hashCode() {
return Objects.hashCode(info);
}Advice 5
private int size = 0;Integer fields are initialized to zero by default; write only
private int size;Advice 6
private Node head = new Node();Use diamond inference:
private Node head = new Node<>();Advice 7
public E next() {
if (!hasNext()) {
throw new IndexOutOfBoundsException("Iterator has reached the end of the list!");
}
...The correct exception is
NoSuchElementException.Advice 8
public void remove() { // only remove once the last node return by next() method.
if (cursor == previous) {
throw new IndexOutOfBoundsException("Cannot remove current node. Last node returned by next() already removed, or reach the head of the list!");
...The correct exception here is
IllegalStateException.Advice 9
Your
contains(Object o) throws a NullPointerException whenever o is null, java.util.ArrayList does not.Advice 10
@SuppressWarnings("rawtypes")
public boolean equals(Object o) {
if (o == null || !(o instanceof SinglyLinkedList)) {
return false;
}
SinglyLinkedList target = (SinglyLinkedList) o;
if (size() != target.size()) {
return false;
}
return hashCode() == target.hashCode();
}What??? If lists are equal in type and size you conclude that they are equal if they have same hash code? Unfortunately, there is a small chance that two different lists have same hash value, so do not rely on it. Instead, you could do:
public boolean equals(Object o) {
if (o == null || !(o instanceof SinglyLinkedList)) {
return false;
}
SinglyLinkedList target = (SinglyLinkedList) o;
if (size() != target.size()) {
return false;
}
Iterator iter1 = iterator();
Iterator iter2 = target.iterator();
while (iter1.hasNext()) {
if (!Objects.equals(iter1.next(), iter2.next())) {
return false;
}
}
return true;
}Advice 11
boolean remove(Object o) has wrong semantics: it removes all occurrences of o; Java lists remove only the first one.Hope that helps.
Code Snippets
public class SinglyLinkedList<E> ... {
...
private static final class Node<E> {
...private T info = null;private T info;public int hashCode() {
if (info == null) {
return 0;
}
return info.hashCode();
}public int hashCode() {
return Objects.hashCode(info);
}Context
StackExchange Code Review Q#153095, answer score: 5
Revisions (0)
No revisions yet.