Using toString Method instead of Print method - java

How can I use the toString method, instead of my custom print method below, in my code? My current code's output is exactly what it is supposed to be, but my instructor wants me "to use toString and get same output". I am confused and do not know how to do it.
Here is my code:
public class LinkedListIntro {
//print method
public static void print(Node temp) {
System.out.print("[");
while (temp.getNext() != null) {
System.out.print(temp.getData() + ", ");
temp = temp.getNext();
}
System.out.println(temp.getData() + "]");
}
public static void main(String[] args) {
Node start = null;
Node temp = null;
for (int i = 1; i <= 5; i++) {
if (start == null) {
start = new Node(i);
temp = start;
} else {
temp.setNext(new Node(i));
temp = temp.getNext();
}
}
//3. printing data
print(start);
//4. removing 4
temp = start;
Node n = temp.getNext();
while (n.getNext() != null) {
if ((int) n.getData() == 4) {
temp.setNext(n.getNext());
n = null;
break;
}
temp = temp.getNext();
n = n.getNext();
}
//5. printing data again after removing 4
print(start);
//6. adding 100 between 1 and 2
temp = start;
Node n1 = temp.getNext();
while (n1.getNext() != null) {
if ((int) temp.getData() == 1) {
temp.setNext(new Node(100));
temp = temp.getNext();
temp.setNext(n1);
}
temp = temp.getNext();
n1 = n1.getNext();
}
//7. printing data again after adding 100
print(start);
//8. removing first node
temp = start;
start = start.getNext();
temp = null;
//printing data after removing 1st node
print(start);
//9. add 0 to beginning
temp = start;
start = new Node(0);
start.setNext(temp);
//printing the final data
print(start);
}
}
public class Node<E>
{
private E data;
private Node next;
public Node(E data) {
this.data = data;
this.next = null;
}
public E getData(){
return data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public String toString() {
return data.toString();
}
}

Use the code in you current print method to build an output string in toString() method of Node. After that, print can just pass the Node temp parameter to System.out.print(), cause it uses toString() internally.
public static void print(Node temp) { //irrelevant method by now
System.out.print(temp);
}
public class Node<E>{
private E data;
private Node next;
//...
public String toString() {
String ouput = "";
Node node = this;
while(node.getNext() != null) {
output += node.getData() +", ";
node = node.getNext();
}
return ouput;
}
}

The toString() methods returns a "string representation" of the object, which means that it returns information about an object as a string. toString() is overridden by the each class that implements it. The global superclass (Object) has a .toString() method but it usually doesn't return the information we want. I think he wants you to make your own toString() that returns a string representation of the Node object. Then you can call System.out.print() on this string to display it.

I would create a toString method which returns a string in LinkedListIntro class which would do what your print method is doing. But instead of printing it would keep appending the value to a string and return the string

I believe what your instructor means is that in the class's toString(), you have to return a string for the entire linked list, not just for the current node.
The trick is that to do it properly, you'll probably need to do it either recursively or with a helper variable. You'll basically need to prepend the current item's data's toString() result to whatever you get from next.
Once you do that, you won't need the print function.

I think your instructor wants you to implement the method toString() in your class.
Every class your create is children of Object class, since this is the superclass for every object. This class has some methods like toString(). In your new class, you should override the method toString(). This method must return a String, which should be a description or some helpfull text about every object of this class.
The purpose of this is that if your new class is cast as Object, when you call the toString() method, it gets the right representation of the new class.
You have a class:
public class SomeClass {
public String text;
public SomeClass() {
text = "hello world";
}
#Override public String toString() {
return (text);
}
}
And in your main function:
public static void main(String[] args) {
//new object of type SomeClass
SomeClass someClass = new SomeClass();
System.out.println(someClass.toString());
//casting it to superclass Object
Object someClass_cast = (Object)someClass;
System.out.println(someClass_cast.toString());
}
Your output will be:
hello world
hello world
I hope this can help you.

Related

Did I write the copy constructor for my Linked List program correctly?

I am working on a project for my Data Structures class that asks me to write a class to implement a linked list of ints.
Use an inner class for the Node.
Include the methods below.
Write a tester to enable you to test all of the methods with whatever data you want in any order.
I have to create three different constructors. One of the constructors is a copy constructor. I have my code down below showing what I did but I'm not sure I wrote this constructor correctly. I also have a method called addToFront one of the many methods I need to implement in this project. Can someone let me know what I would need to write for the copy constructor? I have no idea what I need to write for a copy constructor. I've tried looking it up but the examples shown don't match with what I'm trying to write.
public class LinkedListOfInts {
Node head;
private class Node {
int value;
Node nextNode;
public Node(int value, Node nextNode) {
this.value = value;
this.nextNode = nextNode;
}
}
public LinkedListOfInts() {
}
public LinkedListOfInts(LinkedListOfInts other) {
}
public void addToFront(int x) {
head = new Node(x, head);
}
public String toString() {
String result = " ";
for (Node ptr = head; ptr != null; ptr = ptr.nextNode)
result += ptr.value + " ";
return result;
}
public static void main(String[] args) {
LinkedListOfInts list = new LinkedListOfInts();
for (int i = 0; i < 15; i++)
list.addToFront(i);
System.out.println(list);
}
}
You can iterate over the nodes of the other list and sequentially create new tail nodes based on their values.
public LinkedListOfInts(LinkedListOfInts other) {
Node tail = null;
for(Node n = other.head; n != null; n = n.nextNode){
if(tail == null) this.head = tail = new Node(n.value, null);
else {
tail.nextNode = new Node(n.value, null);
tail = tail.nextNode;
}
}
}
// ...
public static void main(String[] args) {
LinkedListOfInts list = new LinkedListOfInts();
for (int i = 0; i < 15; i++)
list.addToFront(i);
LinkedListOfInts copy = new LinkedListOfInts(list);
System.out.println(list);
System.out.println(copy);
}

How to duplicate every element of a linked list recursively in Java?

I have to write a duplicate function that duplicates every element of a linked list and returns a linked list such that if L = [2,3,4] then duplicate(L) = [2,2,3,3,4,4]. I have to do this recursively. I realize that below is not the correct solution, but I got confused. =(
public class MyList {
int value;
MyList next;
public static MyList duplicate(MyList L){
if(L.next == null){
L.next.value = L.value;
L.next.next = null;
} else {
MyList temp = L.next;
L.next.value = L.value;
L.next.next = temp;
duplicate(L.next);
}
return L;
}
}
First, check that L isn't an empty list (null). If it contains a value, return a new list that has that value repeated twice, followed by duplicating the rest of the list.
By giving MyList a constructor, this is more readable.
public class MyList {
int value;
MyList next;
public MyList(int value, MyList next) {
this.value = value;
this.next = next;
}
public static MyList duplicate(MyList list) {
if (list == null) {
return null;
} else {
return new MyList(list.value,
new MyList(list.value,
duplicate(list.next)));
}
}
}
You currently add an item and then call the recursion on it, ending at endlessly adding items.
You either need to at elements behind your recursion when processing in a forward-direction, or after the recursion when processing backwards.
Let's create a backwards-direction version. We first recursively walk to the end of the list and then resolve the recursion backwards, adding items after our current element each time.
public <E> void duplicateEntries(MyLinkedList<E> list) {
// Do nothing if list is empty
if (list.size() != 0) {
// Call the recursive method on the head node
duplicateEntriesHelper(list.head);
}
}
public <E> void duplicateEntriesHelper(Node<E> node) {
// Walk to the end of the list
if (node.next != null) {
duplicateEntriesHelper(node.next);
}
// Resolve recursion, duplicate current
// entry by inserting it after the current element
Node<E> duplicatedEntry = new Node<>();
duplicatedEntry.data = node.data;
// Insert element after current node
duplicatedEntry.next = node.next;
node.next = duplicatedEntry;
}
The classes I used should look similar to:
public class MyLinkedList<E> {
public Node<E> head = null;
#Override
public String toString() {
// Build something like "MyLinkedList[2, 3, 4]"
StringBuilder sb = new StringBuilder();
sb.append("MyLinkedList[");
StringJoiner sj = new StringJoiner(",");
Node<E> node = head;
while (node != null) {
sj.add(node);
node = node.next;
}
sb.append(sj);
sb.append("]");
return sb.toString();
}
}
public class Node<E> {
public Node next = null;
public E data = null;
#Override
public String toString() {
return E;
}
}
And here is the demo:
public static void main(String[] args) {
// Setup the list
MyLinkedList<Integer> list = new MyLinkedList<>();
Node<Integer> first = new Node<>();
first.data = 2;
Node<Integer> second = new Node<>();
second.data = 3;
Node<Integer> third = new Node<>();
third.data = 4;
list.head = data;
first.next = second;
second.next = third;
// Demonstrate the method
System.out.println("Before: " + list);
duplicateEntries(list);
System.out.println("After: " + list);
}
Of course you can add additional methods and functionality to them. For example using some constructors or getter/setter methods.

I want to populate the list with some user-defined values and eventually print the list. What will be the main()

I want the corresponding main() to implement this code along with explanation. I'm trying to populate the linked list just like an array and eventually printing the elements within this list.
I'm new to Data structures and want to get the concept very clearly and in Java. Any help will be highly appreciated.
My code:
public class LinkedList {
private LinkedList next; //just creating getters and setters for the next node
private int data; //just creating getters and setters for the data
public LinkedList(int data) {
this.data=data; //default constructor to input a value to the node
}
public LinkedList getNext() {
return next; //getter method for the object (probably returns the value of the address of the current object)
}
public void setNext(LinkedList next) {
this.next = next; //setter method for the object (probably to set the address of the next node)
}
public int getData() {
return data; //getter method for the data (probably to get the data of the current node)
}
public void setData(int data) {
this.data = data;//setter method for the data (probably to set the data in the current node)
}
}
dummy sample that you should now improve :)
public static void main(String[] args) {
// populate from array
int[] data = {1,2,3};
LinkedList myList = new LinkedList(0);
LinkedList l = myList;
for (int i = 0 ; i < data.length ; i++) {
l.setData(data[i]);
if (i == data.length - 1) continue;
l.setNext(new LinkedList(0));
l = l.getNext();
}
// print
l = myList;
while(l != null) {
System.out.print(l.getData() + ",");
l = l.getNext();
}
}

Dequeue class printing address instead of QueueNode item

I'm trying to create a Linked List dequeue class that accepts nodes at the head as well as rear. My method, tailRemove() should remove only the item at the tail of the deque. However, when I print it, it's printing the address. The toString() method works fine for all the other methods, so I'm not sure what I'm doing wrong here. Thanks for your help!
public class LinkedDequeue
{
private QueueNode front; //index of current front element
private QueueNode rear; //index of current rear element
private int count; //current # of elements
class QueueNode
{
private Object data;
private QueueNode link;
}
public LinkedDequeue ()
{
front = new QueueNode();
rear = new QueueNode();
count = 0;
}
public void headAdd (Object o)
{
QueueNode temp = new QueueNode();
temp.data = o;
if (isEmpty())
{
front = temp;
rear = front;
front.link = null;
rear.link = null;
}
else
{
temp.link = front;
front = temp;
}
count++;
}
public void tailAdd (Object o)
{
QueueNode temp = new QueueNode();
temp.data = o;
temp.link = null;
if (front == null) front = rear = temp;
else
{
rear.link = temp;
rear = temp;
}
count++;
}
public Object tailPeek()
{
return rear.data;
}
public Object tailRemove()
{
QueueNode temp = new QueueNode ();
QueueNode end = new QueueNode();
if (isEmpty()) return null;
else
{
temp = front;
while (temp.link != rear)
{
temp = temp.link;
}
end = rear;
rear.data = temp.data;
rear.link = null;
count--;
return end;
}
}
public String toString()
{
QueueNode current = front;
StringBuilder elements = new StringBuilder();
while (current != null)
{
elements.append (current.data + "\n");
current = current.link;
}
return elements.toString();
}
public static void main (String [] args)
{
LinkedDequeue list = new LinkedDequeue ();
list.headAdd ("test?");
list.tailAdd("in the middle perhaps");
list.tailAdd ("yikes, does this work?");
System.out.println (list.toString());
System.out.println (list.tailPeek());
System.out.println (list.tailRemove());
}
}
The method tailRemove() returns back an Object of type QueueNode. So when you pass it to System.out.println() it invokes the toString() method of QueueNode class. Since you haven't provided a custom implementation of toString() in your QueueNode class it calls the default implementation in Object class and prints the hashCode of the Object.
Solution :
You need to override toString() method in your QueueNode class as well.
As Kakarot mentioned, creating a toString() method in the QueueNode class will solve the problem. Your end variable, which is what you are printing, doesn't have a custom toString() method.
The reason is that in Java, the default toString() method every object has only prints its memory address. If you want it to do something useful, you need to override it yourself.

how to do this java recursive

I have this code:
static int countStu = 0;
public static int countStudent(Node<Student> lst) {
// pre : true
// post : res = number of students in list
if (lst != null) {
countStu++;
countStudent(lst.getNext());
}
return countStu;
}
The problem with this method is I must declare countStu outside the countStudent() method, which is not good in the case when I want to call countStudent() twice, it will make the returned value doubles. How do I solve this problem and able to call countStudent() unlimited times with correct results?
instead, return((lst == null)? 0 : (1 + countStudent(lst.getNext()))).
Change:
if(lst!=null){
countStu++;
countStudent(lst.getNext());
}
return countStu;
to
return lst==null ? 0 : (1+countStudent(lst.getNext()));
Assuming that this is your homework and you really must declare countStu outside (you shouldn't in any normal code), you can simply wrap the value in some class. Add set+get accessors and pass the object as a second argument to the function. Use it then, instead of the global / static variable.
Or simply don't use the variable at all and return the result + 1. Not sure if this is allowed by your rules.
In general when you are trying to do something like is useful to try to remove the explicit state handling somehow.
For example if you have to compute a function f(x) = G(f(x-1)) you can express G as a stateless method and follow the following pattern:
public static ResultType G(ResultType input) {
// compute G stateless
}
public static ResultType F(int x) {
return G(F(x - 1));
}
That way you don't have any side effects like you have with your current code. The downside is usually minor compared with what you are doing right now (the same stack depth is used overall).
The important thing is to make sure the G and F implementations are stateless (not using variables declared outside the method body scope).
Holding the state of the recursion in the static field would not be thread-safe. Instead hold the value in the stack.
I give you both a recursive example which would risk a StackOverflowError with as little as 6k nodes with a default heap as well as a loop version which doesn't suffer from this.
public class SO3765757 {
public static int countNodeRecursive(Node<?> node) {
if(node == null) {
debug("node is null");
return 0;
}
int count = 1 + countNodeRecursive(node.getNext());
debug(count + " = " + node.toString());
return count;
}
public static int countNodeLoop(Node<?> node) {
int count = 0;
for(Node<?> currentNode = node; currentNode != null; currentNode = currentNode.getNext()) {
count += 1;
debug(count + " = " + currentNode.toString());
}
return count;
}
public static void main(String[] args) {
int count = 10;
if(args.length > 0) {
try {
count = Integer.parseInt(args[0]);
} catch(NumberFormatException e) {
}
}
Node<Student> node = getNodeTest(count);
System.out.println("Loop count = " + countNodeLoop(node));
try {
System.out.println("Recursive count = " + countNodeRecursive(node));
} catch(StackOverflowError e) {
System.out.println("Recursive count caused " + e.getClass().getName());
}
}
private static void debug(String msg) {
System.out.println("DEBUG:" + msg);
}
private static <T> Node<T> getNodeTest(int count) {
Node<T> prevNode = null;
for(int i=0;i<count;i++) {
Node<T> node;
if(prevNode == null) {
node = new NodeImpl<T>();
} else {
node = new NodeImpl<T>(prevNode);
}
prevNode = node;
}
return prevNode;
}
private static interface Node<T> {
Node<T> getNext();
}
private static class NodeImpl<T> implements Node<T> {
private final Node<T> next;
public NodeImpl() {
this.next = null;
}
public NodeImpl(Node<T> next) {
this.next = next;
}
public Node<T> getNext() {
return next;
}
}
private static interface Student {
}
}
countStudent(lst.getNext());
why do i need to call again this , if lst.getNext() has null. precompute before calling recursion, there are different types.when u call this method countStudent from main method , check the lst value for not null , before recursion starts.
public static int
countStudent(Node lst) {
countStu++;
Node<Student> _tmp;
_tmp = lst.getNext();
if (_tmp != null )
countStudent(lst.getNext());
return countStu; }

Categories

Resources