Any time I try to print a MyList object I get 'User#' some hex number.
Can someone help me out with a printing function or a way to print in the main? I heard of trying to Override the toString function, but I couldn't seem to get that to work and am not sure if thats the correct thing to do.
public class MyList {
private ListElement head, tail; //Forward declaration
void add(Object value) {
if (tail != null) {
tail.next = new ListElement(value);
tail = tail.next;
}
else {
head = tail = new ListElement(value);
}
}
Object remove()
{
assert head != null; // don't remove on empty list
Object result = head.value;
head = head.next;
if (head == null) { //was that the last?
tail = null;
}
return result;
}
//Nested class needed only in the implementation of MyList
private class ListElement {
ListElement(Object value) {this.value = value;}
Object value;
ListElement next; //defaults to null as desired
}
public static void main(String[] args) {
myList anInstance = new myList();
String someValue = "A list element";
anInstance.add(someValue);
String anotherValue = "Another value";
anInstance.add(anotherValue);
}
}
The override I tried went something like this:
#Override
public String toString() {
return String.format(this.head);
}
}
You state:
The override I tried went something like this:
#Override
public String toString() {
return String.format(this.head);
}
}
That's a start, now instead of just printing the head, use a while loop to iterate through the entire list, and create a new String that contains the information from all the elements. Then return that String.
i.e.,
#Override
public String toString() {
ListElement tail = this.tail;
// or you might need to start at the head element depending on which way
// you will iterate.
String returnString = "";
// use a while loop here to go through your list
// and add pertinent info from each element to the returnString
return returnString;
}
}
Note that if you were wanting to be super-efficient, you'd use a StringBuilder to do your concatenation, however for your application, this is likely over-kill and not necessary.
Note 2: Hopefully ListElement has a toString() method, and if so, use it inside of your while loop to get each element's info.
Next iteration:
#Override
public String toString() {
String returnString = "";
ListElement currentElement = this.tail;
while (currentElement != null) {
returnString += // *** get toString() info from currentElement
currentElement = // **** reset currentElement to next element
}
return returnString;
}
}
The default toString() method prints the memory address of the object (that Hex number you're seeing).
If you want something different, you need to:
#Override
public String toString()
{
//do stuff to build a string that describes your object
//return that string you just built
}
This code is an untested implementation of the toString method. Try it out.
#Override
public String toString()
{
String myString = "";
ListElement currentElement = head;
while (currentElement.next != null)
{
if (myString.length > 0)
{
myString += ",";
}
myString += currentElement.value.toString();
currentElement = currentElement.next;
}
return myString;
}
Related
I am supposed to build a method that will remove the first instance of a given value in a singly-linked list. However, whenever I try to test this method it will get stuck and I have to force the code to terminate.
edit: following advice, I have made a modified version method Contains that now works well and eliminates pointless repetition of Contains. so happily now the code works as it should!
Here is my code for the method:
public boolean remove(Anything m) {
//INCOMPLETE
if (this.first==null) {
System.out.println("there are no values in the list");
return false;
}
boolean returnValue;
returnValue=false;
if (this.contains(m)==true) {
Node temp=first;
while(temp.next!=null) {
if (temp.next.data==m) {
temp=temp.next.next;
temp.next=null;
returnValue=true;
}
else
returnValue=false;
}
}
return returnValue;
}
Here is my code for testing the method:
list13.addFirst("node5"); list13.addFirst("node4"); list13.addFirst("node3"); list13.addFirst("node2"); list13.addFirst("node1");
System.out.println("5-element list: " + list13);
System.out.println("Testing remove...");
System.out.println(list13.remove("node3"));
and just in case, here is the prebuilt code my assignment came with, if needed:
public class CS2LinkedList<Anything>
{
// the Node class is a private inner class used (only) by the LinkedList class
private class Node
{
private Anything data;
private Node next;
public Node(Anything a, Node n)
{
data = a;
next = n;
}
}
private Node first;
private Node last;
public CS2LinkedList()
{
first = null;
}
public boolean isEmpty()
{
return (first == null);
}
public void addFirst(Anything d)
{
Node temp = first;
first = new Node(d,temp);
}
public void clear()
{
first = null;
}
public boolean contains(Anything value)
{
for (Node curr = first; curr != null; curr = curr.next)
{
if (value.equals(curr.data)) {
return true;
}
}
return false;
}
public String toString()
{
StringBuilder result = new StringBuilder(); //String result = "";
for (Node curr = first; curr != null; curr = curr.next)
result.append(curr.data + "->"); //result = result + curr.data + "->";
result.append("[null]");
return result.toString(); //return result + "[null]";
}
```
Some issues:
At a match, you are reassigning to temp the node that follows after the node to be deleted, and then you clear temp.next. That is breaking the list after the node to be deleted.
The while loop does not change the value of temp when the if condition is not true. So the loop can hang.
You can stop the search when you have identified the node to delete. By consequence you don't need the else inside the while loop.
while(temp.next!=null) {
if (temp.next.data==m) {
// skip the node by modifying `temp.next`:
temp.next = temp.next.next;
returnValue=true;
break; // we removed the targeted node, so get out
}
temp = temp.next; // must move to next node in the list
}
It is a pity that you first iterate the list with this.contains(m), only to iterate it again to find the same node again. I would just remove that if line, and execute the loop that follows any way: it will detect whether the list contains the value or not.
Be aware that your function has no provision for removing the first node of the list. It starts comparing after the first node. You may want to cover this boundary case.
I looked at all of the previous examples and cant see anything that I am doing wrong. I really struggle with null pointer exceptions for some reason and I just cant wrap my head around them.
public class DLBDictionary implements DictionaryInterface {
//Store Strings in an Node
public DLBNode firstNode;
public class DLBNode
{
public char value;
public DLBNode nextValue;
public DLBNode nextLetter;
public DLBNode(){
this.value = '/';
this.nextValue = null;
this.nextLetter = null;
}
public DLBNode(char value){
this.value = value;
this.nextValue = null;
this.nextLetter = null;
}
}
public DLBDictionary() {
DLBNode firstNode = new DLBNode('/');
}
// Add new String to end of list. If String should come before
// previous last string (i.e. it is out of order) sort the list.
// We are keeping the data sorted in this implementation of
// DictionaryInterface to make searches a bit faster.
public boolean add(String s) {
int charIndex = 0;
while(charIndex<=s.length())
{
char currentChar = s.charAt(charIndex);
boolean added = false;
while(!added)
{
if(firstNode.value == '/')
{
firstNode.value = currentChar;
added = true;
}
else if(firstNode.value == currentChar)
{
if(firstNode.nextLetter == null)
{
DLBNode newNode = new DLBNode();
firstNode.nextLetter = newNode;
firstNode = firstNode.nextLetter;
}
else
{
firstNode = firstNode.nextLetter;
}
added = true;
}
else
{
firstNode = firstNode.nextValue;
}
}
charIndex++;
}
DLBNode tempNode = new DLBNode('^');
firstNode.nextLetter = tempNode;
return true;
}
I left off the rest of my code but that last if statement is where I get the exception. It makes no sense to me! Didn't I initialize firstNode's value to '/' in the constructor? So firstNode.getValue should return '/' not a null pointer exception.
You should do
this.firstNode = new DLBNode();
in the constructor of DLBDictionary. You are actually creating a new object rather initializing your firstNode. Hope it helps.
You reset firstNode with several statements in the loop:
firstNode = firstNode.nextValue;
So it will happen that firstNode == null and this causes the NPE. The char value has nothing to do with it, it will be initialised to a character with value 0x00 anyway.
Okay, I have this program almost done, but I'm lost at this point. I'm returning null pointers (it says on line 44 but that's just a while loop) and I need help fixing it please. I use a linked list to implement my queue, and my other two classes pass 100%, so the final class (CarQueue) is where the problem lies that is creating a Null Pointer.
public class CarQueue<E> {
private LinkNode<E> head;
private LinkNode<E> tail;
public CarQueue() {
head = null;
tail = null;
}
public CarQueue(E newData) {
LinkNode<E> temp = new LinkNode<E>(newData, null);
head = temp;
tail = temp;
}
public void addToQueue(E newData) {
LinkNode<E> temp = new LinkNode<E>(newData, null);
if (empty() == false) {
tail.setNext(temp);
tail = temp;
} else {
head = temp;
tail.setNext(temp);
tail = temp;
}
}
public String toString() {
LinkNode<E> temp = head;
String cars = "";
while (temp.getNext() != null) {
cars += temp.toString() + '\n';
}
return cars;
}
public E removeFmQueue() {
LinkNode<E> headReturn = head;
head = head.getNext();
return headReturn.getData();
}
public LinkNode<E> peek() {
return head.getNext();
}
public boolean empty() {
if (head == null)
return true;
else
return false;
}
}
If
while (temp.getNext() != null) {
is the line throwing an exception, then temp is null, (or, if it's even possible, getNext() is throwing a NullPointerException). But let's assume temp is the problem.
temp is being assigned to head, so is head being assigned to null?
If the zero-parameter constructor is called, but no other functions are called before calling toString(), then this would indeed result in temp being assigned null. Therefore, when you attempt temp.getNext(), a NullPointerException is thrown.
To prevent this, you could have an alternative value returned by the toString() method:
public String toString() {
if(head == null) {
return "no head. I got nothing.";
}
//print the other stuff...
}
But, really, the best solution is to never allow head--and therefore temp--to be null, as this means your class is in an unstable and basically-unusable state.
The most obvious way to prevent this is to eliminate the zero-parameter constructor--or alternatively have it only call the other constructor with a non-null value--and ensure that the other constructor never lets head remain as null.
Hey guys I wrote this deleteNode() method that works if I used numbers(int) but doesn't when I try to pass a string in. I'm printing out a String[] list of names and I'm trying to delete a certain name off the list. When I enter a name, it prints "Node not found". Like I said, if I print out a list of numbers it works great but if I change up and print a string it doesnt. Any help is appreciated.
public class BigNode {
public String dataitems;
public BigNode next;
BigNode front ;
public void initList(){
front = null;
}
public BigNode makeNode(String number){
BigNode newNode;
newNode = new BigNode();
newNode.dataitems = number;
newNode.next = null;
return newNode;
}
public boolean isListEmpty(BigNode front){
boolean balance;
if (front == null){
balance = true;
}
else {
balance = false;
}
return balance;
}
public BigNode findTail(BigNode front) {
BigNode current;
current = front;
while(current.next != null){
//System.out.print(current.dataitems);
current = current.next;
} //System.out.println(current.dataitems);
return current;
}
public void addNode(BigNode front ,String number){
BigNode tail;
if(isListEmpty(front)){
this.front = makeNode(number);
}
else {
tail = findTail(front);
tail.next = makeNode(number);
}
}
public void deleteNode(BigNode front, String value) {
BigNode curr, previous = null; boolean found;
if (!isListEmpty(front)){
curr = front;
found = false;
while ((curr.next != null) && (!found)) {
if(curr.dataitems.equals(value)) {
found = true;
}
else {
previous = curr;
curr = curr.next;
}
}
if (!found) {
if(curr.dataitems.equals(value)) {
found = true;
}
}
if (found) {
if (curr.dataitems.equals(front.dataitems)){ // front.dataitems may be wrong .dataitems
front = curr.next;
} else {
previous.next = curr.next;
}
} else {
System.out.println("Node not found!");
//curr.next = null; // Not sure If this is needed
}
}
showList(front);
}
public void printNodes(String[] len){
int j;
for (j = 0; j < len.length; j++){
addNode(front, len[j]);
} showList(front);
}
public void showList(BigNode front){
BigNode current;
current = front;
while ( current.next != null){
System.out.print(current.dataitems + ", ");
current = current.next;
}
System.out.println(current.dataitems);
}
public static void main(String[] args) {
String[] names = {"Billy Joe", "Sally Mae", "Joe Blow", "Tasha Blue"};
BigNode x = new BigNode();
x.printNodes(names);
Scanner in = new Scanner(System.in);
String delete = in.next();
x.deleteNode(x.front, delete);
}
String[] names = {name1, name2, name3, name4}
-First it prints the list, then ask what name to delete.
EDIT: Okay, I've found out what's wrong with the sample code you've posted.
You're calling Scanner.next() which reads a single word. All of your node values are two words. So if I type in "Sally Mae" it's actually just looking for "Sally".
This has nothing to do with the majority of the code in BigNode (although that could certainly be made more elegant). Basically this:
String delete = in.next();
should be
String delete = in.nextLine();
Now I would strongly suggest that you don't just change the code, but instead think about the ways you could have diagnosed this for yourself:
Add logging to your code to show value you were looking for, and each value as you tested it
Use a debugger to step through the code, watching variables
Use unit tests to test the code - those wouldn't have shown you the problem (as it wasn't in code you'd usually write tests for) but they would have given you greater confidence that the problem wasn't in the tested code.
If you try some or preferrably all of those approaches, you'll have learned a lot more from this question than just how to use Scanner...
In various places, you're comparing string references by using the == operator. That will only find your node if you pass in a reference to one of the actual string objects which exists in the list - not a reference to an equal string object.
You want something like:
if (curr.dataitems.equals(value))
(but with careful null checking).
You should be using String.equals comparison instead of == comparison,.
if(curr.dataitems == value) {
should be:
if(curr.dataitems.equals(value) {
You do comparisons with ==. For int this compares the values, but for String only the references. So is you want to remove a String with the same value but in different objects this will fail.
Use String.equals() instead.
You should always use equals() for comparing object values, not == . For instance, in your code this line:
curr.dataitems == value
should have been written as:
curr.dataitems.equals(value)
I am looking at examples getting ready for an exam, and frankly, I am not very good with either recursion or lists, but particularly lists.
A node class is given, it will hold strings (not generic) write a recursive java function called concat that takes a node representing the head of a linked list and returns a string representing the concatenation of all the elements of the list if the list is empty the string should be as well.
Any help would be appreciated.
(The following is what I had type before I asked the question:)
public static String FindConcat(Node head) {
String s = "";
if(head == null) return s;
else if(head.next = null) {
s += head.data;
return s;
}
else {
}
}
Thanks for the repsonses.
In this case what recursion is finding the base case and how to "devide" the data down to this base case. So first define your "base case".
Base case: argument to the function is null
Till you get the the base case, append the text of the node and skip the first element
This is your method:
public static String FindConcat(Node head) {
if (head == null)
return ""; // base case
// devide it down (run recursive FindConcat on the _next_ node)
return head.data + FindConcat(head.next);
}
This simple example will print hello this is a linked list:
public class Test {
// this is a very basic Node class
static class Node {
String text;
Node next;
public Node(String text) {
this.text = text;
}
// used for building the list
public Node add(String text) {
next = new Node(text);
return next;
}
}
// this is the recursive method concat
public static String concat(Node node) {
if (node == null)
return "";
return node.text + " " + concat(node.next);
}
public static void main(String[] args) {
// build the list
Node head = new Node("hello");
head.add("this").add("is").add("a").add("linked").add("list");
// print the result of concat
System.out.println(concat(head));
}
}
If your node is null, return an empty string.
Otherwise, get the string, make a recursive call (to get the concatenated result for the rest of the nodes), and append that to the string and return the result.
since this sounds like homework, i'll make a suggestion.
start by writing the method that will work if the list only has one element (ie there is no next node). use that as the basis for your recursive call.
Recursive traversal of a linked list generally looks like seeing if you're at the end of the list (the reference you got was null), and if you're not, doing something to a recursive call upon the next element of the list, and if you are, doing the base case thing. Assuming that nodes look like this from the outside:
public class Node{
public Node getNext();
public String toString();
}
...your method looks like this (inside the class you're using to run this out of):
public String concatList(Node head){
if(head == null){
return ""; //empty list is a null pointer: return empty string
}
return head.toString() + concatList(head.getNext());
}
The end of the list, or no list at all, looks the same- a null pointer- and returns the blank string, as specified; everything else takes the current node and concatenates it to the list created by getting the concatenated version of the entire remainder of the string.
Be careful: if something's corrupted your list so it's actually a loop, this has no checks for that and will run forever until it runs out of stack memory, unless Java correctly detects the loop optimization of this recursive function and it will simply run forever.
Here is a very complete example:
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
public class RecurisveLinkedListExample
{
public static String concat(final Node node)
{
if (node == null)
{
return "";
}
else
{
return node.getData() + concat(node.getNext());
}
}
public static void main(String[] args)
{
final List<String> input = Arrays.asList("A", "B", "C", "D");
final Node head = new Node(null, input.get(0));
Node previous = head;
for (int i = 1; i < input.size(); i++)
{
previous = previous.addNext(input.get(i));
}
System.out.println(concat(head));
}
public static class Node
{
private final UUID id;
private final Node previous;
private final String data;
private Node next;
public Node(final Node previous, final String data)
{
this.previous = previous;
this.data = data;
this.next = null;
this.id = UUID.randomUUID();
}
public Node getPrevious()
{
return previous;
}
public String getData()
{
return data;
}
public Node addNext(final String data)
{
this.next = new Node(this, data);
return this.next;
}
public Node getNext()
{
return next;
}
#Override
public String toString()
{
return String.format("%s:%s:%s",
this.previous == null ? "HEAD" : this.previous.id,
this.data,
this.next == null ? "TAIL" : this.next.id);
}
}
}