问题
I am writing a generic singly linked list as a homework assignment. I have been given the JUnit test that the instructor is going to use to test the code. When I run the test, gives me this error: java.lang.ClassCastException: SinglyLinkedList$Node cannot be cast to java.lang.Integer. If I am using a generic as the type, why can't I cast it as an Integer?
Also, when I first ran the test, the bash showed: JUnit version 4.12 .E.E.E. And it stayed like this until I ended the process. I think this may be a sign of an infinite loop, but even looking at my code, I can't find where it would be infinite.
This is my SinglyLinkedList class
import java.util.Iterator;
import java.util.NoSuchElementException;
public class SinglyLinkedList<E> implements Iterable<E>{
private Node<E> head;
private Node<E> tail;
public SinglyLinkedList() {
head = new Node<E>(null, tail);
tail = new Node<E>(null, null);
}
/**
* Insert at the end of the list
* @param E
*/
public void add(E element) {
Node<E> place = head;
if(head.getNext() == null){
Node node = new Node(element,tail);
head.setNext(node);
}
else{while(place.next != tail){
place = place.getNext();
Node node = new Node(element, tail);
place.setNext(node);
}
}
}
/**
* Remove element from the list
* @param E
*/
public void remove(E element){
Node place = head;
Node prev = head;
while(place.getElement() != element){
prev = place;
place = place.getNext();
}
prev.setNext(place.getNext());
}
/**
* Clear all elements
*/
public void clear(){
head.setNext(null);
}
/**
* Gets the Nth to last node
* @param int n
* @return E
*/
public E getNthToLast(int n){
int length = 0;
Node temp = head;
while(temp.getNext() != tail){
temp = temp.getNext();
length++;
}
if(length < n){
throw new NoSuchElementException();
}
temp = head;
for(int i = 0; i < length - n+1; i++){
temp = temp.getNext();
}
return (E) temp.getElement();
}
/**
* Creates new Iterator
* @return SinglyLinkedListIterator
*/
@Override
public SinglyLinkedListIterator iterator(){
return new SinglyLinkedListIterator();
}
private class Node<E> {
private E element;
private Node<E> next;
public Node(E element, Node next) {
this.element = element;
this.next = next;
}
public void setNext(Node next){
this.next = next;
}
public Node getNext(){
return this.next;
}
public void setElement(E element){
this.element = element;
}
public E getElement(){
return this.element;
}
}
public class SinglyLinkedListIterator implements Iterator<E> {
private Node curr = head;
Node prev = head;
/**
* Gets the next node
* @return E
*/
@Override
public E next() {
if(curr.getNext() != tail){
prev = curr;
curr = curr.getNext();
return (E) curr;
}
else{
throw new NoSuchElementException();
}
}
@Override
public boolean hasNext() {
if(curr.getNext() != null){
return true;
}
else{return false;}
}
@Override
public void remove() {
if(curr != tail){
prev.setNext(curr.getNext());
}else{throw new IllegalStateException();}
}
public void add(E element){
Node node = new Node(element, curr.getNext());
curr.setNext(node);
}
}
}
This is the JUnit test:
import java.util.Iterator;
import java.util.NoSuchElementException;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.ExpectedException;
public class TestLinkedList{
private SinglyLinkedList<Integer> list;
@Rule // this rule allows one of the tests to verify that an exception is thrown
public ExpectedException thrown = ExpectedException.none();
@Before
public void setUp(){
list = new SinglyLinkedList<>();
SinglyLinkedList<Integer>.SinglyLinkedListIterator it = list.iterator();
for(int i = 9; i > 0; i--){
it.add(new Integer(i));
it.next();
}
// Question to all: The process of adding numbers to the list could
// have been simplified by dispensing with the iterator and simply
// calling SinglyLinkedList's add() method. Why use the iterator?
// What benefit does it provide over SinglyLinkedList's add?
}
/**
* Ensure that the linked list holds the expected values after the
* initialization in the setup() method. This initialization used the
* list iterator to perform the adds.
*/
@Test
public void testIteratorAdd(){
Iterator<Integer> it = list.iterator();
Integer listElement;
for(int i = 9; i > 0; i--){
listElement = it.next();
assertEquals(i, listElement.intValue());
}
}
/**
* Ensure that the list is built correctly if the list's add method is
* used instead of the iterator's add method.
*/
@Test
public void testListAdd(){
list.clear();
for(int i = 9; i > 0; i--){
list.add(new Integer(i));
}
Iterator<Integer> it = list.iterator();
Integer listElement;
for(int i = 9; i > 0; i--){
listElement = it.next();
assertEquals(i, listElement.intValue());
}
}
/**
* Remove all the odd numbers using the list's remove method and ensure
* that the remaining elements are as expected (the even numbers 8, 6,
* 4, and 2).
*/
@Test
public void testListRemove(){
list.remove(9);
list.remove(7);
list.remove(5);
list.remove(3);
list.remove(1);
Iterator<Integer> it = list.iterator();
int evenNum = 8;
while(it.hasNext()){
assertEquals(evenNum,it.next().intValue());
evenNum = evenNum - 2;
}
}
/**
* Remove all the even numbers using the iterators's remove method and ensure
* that the remaining elements are as expected (the odd numbers 9, 7,
* 5, 3, and 1).
*/
@Test
public void testIteratorRemove(){
// first, remove all the even numbers
Iterator<Integer> it = list.iterator();
while(it.hasNext()){
Integer theVal = it.next().intValue();
if( theVal.intValue() % 2 == 0){
it.remove();
}
}
// Next, check that the list contains the correct
// remaining numbers
it = list.iterator();
int oddNum = 9;
while(it.hasNext()){
assertEquals(oddNum,it.next().intValue());
oddNum = oddNum - 2;
}
}
/**
* Attempt to remove from an empty list and ensure that the
* IllegalStateException is thrown
*/
@Test
public void testEmptyRemove(){
list.clear();
thrown.expect(IllegalStateException.class);
Iterator<Integer> it = list.iterator();
it.remove();
}
/**
* Attempt to call next() when already at the end of the list and
* ensure that the NoSuchElementException is thrown.
*/
@Test
public void testInvalidNext(){
list.clear();
thrown.expect(NoSuchElementException.class);
Iterator<Integer> it = list.iterator();
it.next();
}
/**
* Test the getNthToLast method.
*
* As an example, given the numbers that is list holds:
* 9 8 7 6 5 4 3 2 1
* the 2nd to last element is 2, the 3rd to last
* is 3, and so on.
*
* Ensure that the getNthToLast returns 4 when requested the 4th to
* last element.
*/
@Test
public void testGetNthToLast(){
Integer ans = list.getNthToLast(4);
assertEquals(new Integer(4),ans);
}
}
回答1:
Code cleanup
You have a lot of raw types, which complicate finding the broken code, you want to explicity say that Node
s are Node<E>
s.
Main issue
return (E) curr;
You are returning the node and trying to cast it, causing problems, it should be:
return curr.element;
来源:https://stackoverflow.com/questions/46476547/singly-linked-list-node-not-able-to-be-cast-as-integer