I am having trouble implementing the remove method in the List class. I am first writing the objects out into a file, then I am retrieving those objects and putting them inside a linked list. However, when I try to check for equality by going over the entire linked list I get not matches even though I know for sure that object is in there. I can't even get .equals to work it seems.
package ProjectOne;
public class List<T> {
private LLNode<T> list;
private int numberOfNodes = 0;
private LLNode<T> location;
private LLNode<T> previous;
protected boolean found;
public List() {
list = null;
}
public void add(T element) {
if (numberOfNodes == 0) {
list = new LLNode<T>(element);
numberOfNodes++;
}
else {
LLNode<T> newNode = new LLNode<T>(element);
newNode.setLink(list);
list = newNode;
}
}
public void find(T target) {
location = list;
found = false;
while(location !=null) {
System.out.println(target.equals(location.getInfo()));
if(location.getInfo().equals(target)) {
found = true;
return;
}
else {
previous = location;
location = location.getLink();
}
}
}
public boolean remove(T element) {
this.find(element);
if(found) {
if(list == location) list = list.getLink();
else previous.setLink(location.getLink());
}
return found;
}
public LLNode<T> getList() {
return list;
}
public String toString() {
LLNode<T> currentNode = list;
String info = "";
while(currentNode !=null) {
info +=currentNode.getInfo();
currentNode = currentNode.getLink();
}
return info;
}
}
These are one of many objects I am writing out to the file
Patient p1 = new Patient("Alex", "1123 metropolitan", new Date("11/20/1997"));
p1.setFirstVisit(new Date("11/20/1997"));
p1.setHeight(72);
p1.setLastVisit(new Date("11/20/1997"));
p1.setWeight(200);
out.writeObject(p1);
Patient p2 = new Patient("John", "200 avenue of americas", new Date("12/20/1999"));
p2.setFirstVisit(new Date("11/11/2005"));
p2.setHeight(5);
p2.setLastVisit(new Date("11/21/2010"));
p2.setWeight(150);
out.writeObject(p2);
Patient p3 = new Patient("Sarah", "Park avenue", new Date("09/07/1960"));
p3.setFirstVisit(new Date("05/11/1977"));
p3.setHeight(75);
p3.setLastVisit(new Date("01/21/2017"));
p3.setWeight(110);
out.writeObject(p3);
Patient p4 = new Patient("Malcolm", "56street", new Date("05/28/1977"));
p4.setFirstVisit(new Date("01/11/1990"));
p4.setHeight(75);
p4.setLastVisit(new Date("8/21/2016"));
p4.setWeight(155);
out.writeObject(p4);
However, when I call System.out.println(list.remove(p1));
I get the output
false
false
false
false
false
with the last being the return result of the method and the first four just trying to debug.
Make sure that you override equals and hashcode methods in Patient class.
Related
for uni we are supposed to implement an iterator for a String linked list by ourselves. But the infos how to do that was pretty small. So we tried it by ourselves and googled a lot but all the explanations we found dont include the whole code and I dont get how to implement the iterator correct. I think everything works fine as long as we use the for each loop to use the iterator but as soon as we are trying to use the "while (iterator.hasnext) { next }" thing it stays in the first element of the linked list. I think I know this problem is based on that we are always instantiating a new iterator but I dont get how to implement it else. Hopefully someone can help, I really don't know what to do, I tried everything..
import java.util.Iterator;
import java.util.NoSuchElementException;
public class LinkedList implements Iterable<String> {
// ---------- Attributes ----------
private int size = 0;
private Node head = null;
// private Iterator<String> linkedListIterator = this.iterator(); // ??
static class Node {
// ---------- Attributes ----------
private String object;
private Node next;
// ---------- Constructors ----------
public Node(String object, Node node) {
this.object = object;
this.next = node;
}
public Node() {
this(null, null);
}
// ---------- Getter, Setter ----------
public String getElement() {
return this.object;
}
public void setElement(String object) {
this.object = object;
}
public Node getNext() {
return this.next;
}
public void setNext(Node node) {
this.next = node;
}
}
class LinkedListIterator implements Iterator<String> {
// ---------- Attributes ----------
private Node currentNode = null;
private int counter = 0;
// ---------- Constructor ----------
public LinkedListIterator(LinkedList linkedList) {
this.currentNode = linkedList.head;
}
// ---------- Getter, Setter, Methods ----------
public boolean hasNext() {
return this.currentNode != null;
}
public String next() {
if (!this.hasNext()) {
System.out.println("Fehler: ");
throw new NoSuchElementException();
}
String object = this.currentNode.getElement(); // ?
this.currentNode = this.currentNode.getNext();
this.counter++;
return object;
}
public int getCounter() {
return this.counter;
}
}
// ---------- Getter, Setter, Methods ----------
public Node getHead() {
return this.head;
}
public void addFirst(String object) {
// new node as head
Node newNode = new Node(object, this.head);
this.head = newNode;
this.size++;
}
public String getFirst() { //throws ListEmptyException {
if (isEmpty()) {
// throw new ListEmptyException();
}
return this.head.getElement();
}
public String removeFirst() { //throws ListEmptyException {
if (isEmpty()) {
// throw new ListEmptyException();
}
String object = this.head.getElement();
this.head = this.head.getNext();
return object;
}
public boolean isEmpty() {
return this.head == null;
}
public int getSize() {
return this.size;
}
#Override
public Iterator<String> iterator() {
System.out.println("helo");
return new LinkedListIterator(this);
}
public String toString() {
String output = "";
// this is working:
// for (String element: this) {
// output += element + "\n";
// }
while (this.iterator().hasNext()) {
System.out.println(this.iterator().hasNext());
output += this.iterator().next() + "\n";
}
return output;
}
public static void main(String[] args) {
LinkedList ll = new LinkedList();
ll.addFirst("a");
ll.addFirst("b");
ll.addFirst("c");
ll.addFirst("d");
ll.addFirst("e");
System.out.println(ll.toString());
}
}
Problem solved by this
But new question: Why is this working
public String toString() {
String output = "";
Iterator<String> iterator = this.iterator();
while (iterator.hasNext()) {
output += it.next() + "\n";
}
return output;
}
But this not
public class LinkedList implements Iterable<String> {
private Iterator<String> linkedListIterator = this.iterator();
public String toString() {
String output = "";
while (this.linkedListIterator.hasNext()) {
output += this.linkedListIterator.next() + "\n";
}
return output;
}
}
Your implementation of LinkedListIterator is correct, the problem is in the toString() method.
You are calling this.iterator() 3 times, so each time you return a new instance of LinkedListIterator.
Instead you have to call this.interator() only once and use the instance you get.
Like this:
Iterator<String> it=this.iterator();
while (it.hasNext()) {
System.out.println(it.hasNext());
output += it.next() + "\n";
}
Regarding the new question.
If you instantiate the private Iterator<String> linkedListIterator attribute in the body of the class, (Something that should never be done), every time you refer to it you will make a call to the public Iterator<String> iterator() method and you will get a new instance of LinkedListIterator.
You are making the same mistake as in the beginning.
This is an example of why attributes should be instantiated only within a method declaration.
Remember that an iterator can only move forward, if you want to restart it you must create a new instance. That's what you do by calling this.iterator().
I recommend you to use some debugging tools so you can see the instructions that are executed
Also, there is a design pattern that deals iterators.
https://en.wikipedia.org/wiki/Iterator_pattern
I'm having trouble figuring out why my code won't parse through the ListNodes in the Lists, in order to add a new String as a ListNode. I'm trying to write the function add(String s), to add a new ListNode to the List. If the list is empty, I just add the String as a ListNode, and if not, I parse through using node and myNext, and then if node.myNext is null, I replace it with the newly created ListNode. What is the reason this isn't working? It either does not throw an output or it says it is out of bounds.
public class List {
private ListNode myHead;
private int mySize;
public List() {
this.myHead = null;
this.mySize = 0;
}
public class ListNode {
public String myData;
public ListNode myNext;
public ListNode(String element, ListNode next) {
this.myData = element;
this.myNext = next;
}
public ListNode(String element) {
this(element, null);
}
public boolean isEmpty() {
return this.length() == 0;
}
public void add(String s) {
if(this.isEmpty() == true) {
this.addToFront(s);
}
else {
this.mySize++;
for(ListNode node = this.myHead; node.myData != null; node = node.myNext) {
if(node.myNext == null) {
ListNode lno = new ListNode(s, null);
node.myNext = lno;
}
else {
node.myData = node.myData;
}
}
}
}
In you ListNode you can't access methods and variables of your List class.
Assuming that you want to add the new String at the top of your List you should do something like this:
public class List {
private ListNode myHead;
private int mySize;
public List() {
this.myHead = null;
this.mySize = 0;
}
public boolean isEmpty() {
return this.mySize == 0;
}
public void add(String s) {
this.myHead = new ListNode(s, myHead);//add new String as head element
this.mySize++;
}
}
public class ListNode {
public String myData;
public ListNode myNext;
public ListNode(String element, ListNode next) {
this.myData = element;
this.myNext = next;
}
public ListNode(String element) {
this(element, null);
}
}
If you want to add it at the end of your List you can try it like this:
public void add(String s) {
if(this.isEmpty()){
this.myHead = new ListNode(s, myHead);//add new String as head element
}else{
ListNode node = this.myHead;
while (node.myNext != null){
node = node.myNext;
}
//now you hav the last node of your list
node.myNext = new ListNode(s,null);
}
this.mySize++;
}
The code you have pasted is not complete.
Also, If I am correct, your List is having the ListNodes and thus, it is your List where you should put methods to check if it is Empty (does not have any ListNodes in it) or add, delete, count, search etc. functions.
For isEmpty(), There is no length() defined, so simply check the size to be == 0.
For add(), if it is empty just point myHead to your new ListNode; If you have to add in end, iterate the myHead using a currentNode reference, till its next is null and add.
If it is to be in middle somewhere, you will need to check for ListNode myData to decide where it fits white moving from myHead towards null and once you find a place to insert, you will need to change the [PrevNode] -> new ListNode -> [nextNode]
Right now I am trying to create a circular list, where when I use hasNext() from an Iterator it should always return true. However right now it is returning that it is not a circular list, and I am also having problems printing out the values (in this example Strings) of the ArrayList. Here is the CircularList class I created, which has a inner Node class for the objects that are put into the list:
public class CircularList<E> implements Iterable{
private Node<E> first = null;
private Node<E> last = null;
private Node<E> temp;
private int size = 0;
//inner node class
private static class Node<E>{ //In this case I am using String nodes
private E data; //matching the example in the book, this is the data of the node
private Node<E> next = null; //next value
//Node constructors, also since in this case this is a circular linked list there should be no null values for previous and next
private Node(E data){
this.data = data;
}
}
//end of inner node class
public void addValue(E item){
Node<E> n = new Node<E>(item);
if(emptyList() == true){ //if the list is empty
//only one value in the list
first = n;
last = n;
}
else{ //if the list has at least one value already
//store the old first value
temp = first;
//the new first is the input value
first = n;
//next value after first is the old first value
first.next = temp;
//if after this there will be only two values in the list once it is done
if(size == 1){
last = temp;
}
//if the list is greater than one than the last value does not change, since any other values will be put before last in this case, and not replace it
//creating the circular part of the list
last.next = first;
}
size++;
}
public boolean emptyList(){
boolean result = false;
if(first == null && last == null){ //if there is no values at all
result = true;
}
return result;
}
#Override
public Iterator<E> iterator() {
// TODO Auto-generated method stub
return new CircularIterator<E>(); //each time this method is called it will be creating a new instance of my Iterator
}
}
Here is the Iterator class I am making:
public class CircularIterator<E> implements Iterator<E> {
#Override
public boolean hasNext() {
return false;
}
#Override
public E next() {
// TODO Auto-generated method stub
return null;
}
#Override
public void remove() {
// TODO Auto-generated method stub
}
}
and finally the Test class:
public class Test {
static CircularList<String> c = new CircularList<String>(); //in this case it is a string list
static Iterator it = c.iterator();
public static void main(String[]args){
c.addValue("Bob");
c.addValue("Joe");
c.addValue("Jaina");
c.addValue("Hannah");
c.addValue("Kelly");
Iterate();
for(String val : c){
System.out.println(val);
}
}
private static boolean Iterate(){
boolean result = false;
if(!it.hasNext()){
System.out.println("Not a circular list!");
}
else{
result = true;
}
return result;
}
}
Again I am trying to get it to always return true, I think the problem lies with my hasNext() method, but I am not completely sure.
The main problem with your approach is you are using static inner classes - this is not necessary. Making the outer class generic is sufficient. The generic parameter is then inherited by the inner classes and all sorts of issues disappear.
Implementing an Iterator properly is subtle.
public static class CircularList<E> implements Iterable<E> {
private Node first = null;
private Node last = null;
private int size = 0;
private class Node {
private E data;
private Node next = null;
private Node(E data) {
this.data = data;
}
}
public void addValue(E item) {
Node n = new Node(item);
if (emptyList()) {
//only one value in the list
first = n;
last = n;
} else { //if the list has at least one value already
//store the old first value
Node temp = first;
//the new first is the input value
first = n;
//next value after first is the old first value
first.next = temp;
//if after this there will be only two values in the list once it is done
if (size == 1) {
last = temp;
}
//if the list is greater than one than the last value does not change, since any other values will be put before last in this case, and not replace it
//creating the circular part of the list
last.next = first;
}
size++;
}
public boolean emptyList() {
boolean result = false;
if (first == null && last == null) { //if there is no values at all
result = true;
}
return result;
}
#Override
public Iterator<E> iterator() {
return new CircularIterator(); //each time this method is called it will be creating a new instance of my Iterator
}
private class CircularIterator implements Iterator<E> {
// Start at first.
Node next = first;
public CircularIterator() {
}
#Override
public boolean hasNext() {
// Stop when back to first.
return next != null;
}
#Override
public E next() {
if (hasNext()) {
E n = next.data;
next = next.next;
if (next == first) {
// We're done.
next = null;
}
return n;
} else {
throw new NoSuchElementException("next called after end of iteration.");
}
}
}
}
public void test() {
CircularList<String> c = new CircularList<>();
c.addValue("A");
c.addValue("B");
c.addValue("C");
c.addValue("D");
for (String s : c) {
System.out.println(s);
}
}
Your main code was essentially correct - all I did was remove the unnecessary generics parameters from the inner classes.
Note that the way you add node to the list means that the items come out backwards. You could adjust that in your addValue method quite easily.
You can simply use following for circular iteration. This Circular list behave as same as other java.util.Lists. But it's iteration is modified. You don't need to care about it's performance tuning additionally. Because it's super class (LinkedList) is already well tested and enough stronger to use.
`public class CircularList extends LinkedList {
#Override
public Iterator<E> iterator() {
return createIterator();
}
//create new iterator for circular process
private Iterator<E> createIterator() {
return new Iterator<E>() {
private int index = 0;
#Override
public boolean hasNext() {
//no elements when list is empty
return isEmpty();
}
#Override
public E next() {
E node = get(index);
//rotate index
index++;
if (index == size()) {
index = 0;
}
return node;
}
};
}
}`
I am writing a Graph class,
I keep a HashMap in which ids of nodes (int values) are mapped to the associated nodes, and I'm using adjacency list approach to keep edges starting from a node (keeping them in form of a HashSet)
Note that : This graph is directed and unweighted,
I want to implement a method which returns an iterator over objects of class Edge :
When getting next on this iterator , one will get an object of class Edge which is created right when it's being traversed, and if there's no more neighbors for a node, it goes to the next node (order is not important) and if there's no more starting nodes (all are traversed), it finishes.
Any idea on how to implement this iterator on the edges without previously keeping the edges in Edge class objects ?
class Graph{
HashMap<Integer , GraphNode> nodes;
public Graph(){
nodes = new HashMap<Integer ,GraphNode>();
}
public boolean addEdge(GraphNode n1 , GraphNode n2){
if (!nodes.containsKey(n1) || !nodes.containsKey(n2))
return false;
return n1.addNeighbor(n2);
}
public boolean addNode(int id){
if (nodes.containsKey(id))
return false;
nodes.put(id , new GraphNode(id));
return true;
}
public boolean removeNode(GraphNode n1){
if (!nodes.containsKey(n1.content))
return false;
for (GraphNode m : n1.neighbors)
m.removeNeighbor(n1);
nodes.remove(n1);
return false;
}
public boolean removeEdge(GraphNode n1 , GraphNode n2){
if (!nodes.containsKey(n1) || !nodes.containsKey(n2))
return false;
return n1.removeNeighbor(n2);
}
public Iterator<GraphNode> NodeIterator(){
return nodes.values().iterator();
}
public Iterator<Edge> EdgeIterator(){
Iterator<GraphNode> itr = this.NodeIterator();
while (itr.hasNext){
GraphNode n = itr.next();
//......
}
}
}
class GraphNode{
HashSet<GraphNode> neighbors;
int content;
public GraphNode(int content){
this.content = content;
neighbors = new HashSet<GraphNode>();
}
boolean addNeighbor(GraphNode n){
if (neighbors.contains(n))
return false;
neighbors.add(n);
return true;
}
boolean removeNeighbor(GraphNode n){
if (!neighbors.contains(n))
return false;
neighbors.remove(n);
return true;
}
}
class Edge{
Node start , end;
public Edge(Node start , Node end){
this.start = start;
this.end = end;
}
}
I think something like this might work :
public Iterator<Edge> EdgeIterator(){
Iterator <Edge> edgeIter = new Iterator<Edge>() {
private Iterator<GraphNode> itr = this.NodeIterator();
private GraphNode currentNode;
... // additional private members as required
public void remove()
{
// you don't have to implement this method if you don't need to support
// this operation
}
public Edge next()
{
if (!hasNext())
throw new NoSuchElementException ();
return new Edge (x , y); // where you find x & y based on the current state
// of the iterator (kept in the private members of
// this instance)
}
public boolean hasNext()
{
return ?; // you return a boolean value based on the current state
// of the iterator (kept in the private members of
// this instance)
}
};
return edgeIter;
}
The EdgeIterator method creates an Iterator<Edge> and defines the methods of the Iterator interface (I left the implementation of these methods to you). The Iterator instance contains an instance of Iterator<GraphNode>, which it uses to iterate over the nodes.
You should add to the iterator some additional private members that keep track of the current node (the last node returned by the node iterator) and the current edge you are iterating on. Whenever you finish iterating over the edges of a node, you get the next node using itr.next() (after checking there is a next node available). next() of the edge iterator can construct the next Edge based on those private members.
As Eran said , I completed the code of the iterator methods ,
Do you think this one works ?
public Iterator<Edge> EdgeIterator(){
Iterator<Edge> edgeIter = new Iterator<Edge>() {
private Iterator<GraphNode> node_itr = NodeIterator();
private Iterator<GraphNode> neighbor_itr;
private GraphNode current_node;
private GraphNode current_neighbor;
public void remove()
{
if (current_node == null || current_neighbor == null)
return;
current_node.removeNeighbor(current_neighbor);
}
public Edge next()
{
if (neighbor_itr == null || !neighbor_itr.hasNext())
if (node_itr.hasNext()){
current_node = node_itr.next();
neighbor_itr = current_node.neighbors.iterator();
}else
return null;
current_neighbor = neighbor_itr.next();
return new Edge(current_node , current_neighbor);
}
public boolean hasNext()
{
if (neighbor_itr == null || !neighbor_itr.hasNext())
if (node_itr.hasNext())
return node_itr.next().neighbors.iterator().hasNext();
else
return false;
return true;
}
};
return edgeIter;
}
Update : The edited/working version :
public Iterator<Edge> EdgeIterator(){
Iterator<Edge> edgeIter = new Iterator<Edge>() {
private Iterator<GraphNode> node_itr = NodeIterator();
private Iterator<GraphNode> neighbor_itr;
private GraphNode current_node;
private GraphNode current_neighbor;
public void remove()
{
if (current_node == null || current_neighbor == null)
return;
current_node.removeNeighbor(current_neighbor);
}
private void moveNext(){
if (neighbor_itr == null || !neighbor_itr.hasNext()){
while (node_itr.hasNext()){
current_node = node_itr.next();
neighbor_itr = current_node.neighbors.iterator();
if (neighbor_itr.hasNext()){
break;
}
}
}
}
public Edge next()
{
moveNext();
current_neighbor = neighbor_itr.next();
return new Edge(current_node , current_neighbor);
}
public boolean hasNext()
{
moveNext();
return neighbor_itr.hasNext();
}
};
return edgeIter;
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I implement a Linked List in Java?
We know there is no pointers in java. Then what is the best way to build the link list in java?
The best way is to not build it. Java already has a LinkedList class amongst its rather large selection of collection classes.
You would be better off using what the language/library already provides.
You have an object that essentially contains two variables, no methods (bare minimum; however, you could have methods if you wanted). Something like:
class Link
{
int data;
Link next;
}
Then you create a new Link like any other object. Set the data to the data you want a node to hold. Then set the Link node to the node that it will be "pointing" to (or null if it doesn't point to another one).
Note: you can also have a previous node (which points to the previous node) if need be.
try having this code.
public class Main {
public static void main(String[] args) {
LinkedList theList = new LinkedList();
LinkedListIterator theItr;
theItr = theList.zeroth();
printList(theList);
for (int i = 0; i < 10; i++) {
theList.insert(new Integer(i), theItr);
printList(theList);
theItr.advance();
}
System.out.println("Size was: " + listSize(theList));
}
public static int listSize(LinkedList theList) {
LinkedListIterator itr;
int size = 0;
for (itr = theList.first(); itr.isValid(); itr.advance())
size++;
return size;
}
public static void printList(LinkedList theList) {
if (theList.isEmpty())
System.out.print("Empty list");
else {
LinkedListIterator itr = theList.first();
for (; itr.isValid(); itr.advance())
System.out.print(itr.retrieve() + " ");
}
System.out.println();
}
}
class LinkedList {
public LinkedList() {
header = new ListNode(null);
}
public boolean isEmpty() {
return header.next == null;
}
public void makeEmpty() {
header.next = null;
}
public LinkedListIterator zeroth() {
return new LinkedListIterator(header);
}
public LinkedListIterator first() {
return new LinkedListIterator(header.next);
}
public void insert(Object x, LinkedListIterator p) {
if (p != null && p.current != null)
p.current.next = new ListNode(x, p.current.next);
}
public LinkedListIterator find(Object x) {
ListNode itr = header.next;
while (itr != null && !itr.element.equals(x))
itr = itr.next;
return new LinkedListIterator(itr);
}
public LinkedListIterator findPrevious(Object x) {
ListNode itr = header;
while (itr.next != null && !itr.next.element.equals(x))
itr = itr.next;
return new LinkedListIterator(itr);
}
public void remove(Object x) {
LinkedListIterator p = findPrevious(x);
if (p.current.next != null)
p.current.next = p.current.next.next; // Bypass deleted node
}
private ListNode header;
}
class LinkedListIterator {
LinkedListIterator(ListNode theNode) {
current = theNode;
}
public boolean isValid() {
return current != null;
}
public Object retrieve() {
return isValid() ? current.element : null;
}
public void advance() {
if (isValid())
current = current.next;
}
ListNode current;
}
class ListNode {
public ListNode(Object theElement) {
this(theElement, null);
}
public ListNode(Object theElement, ListNode n) {
element = theElement;
next = n;
}
public Object element;
public ListNode next;
}