regarding this keyword (java) - java

I have a question regarding the output of the following program. The output is null. This is what I thought as well. Im thinking its because the methods called before display simply modify a copy of head and not head itself. Im assuming that I could get around this using a this.head= something right?
Heres the code:
public class List {
private Node head;
public List (){
int max=3;
int i;
head=null;
Node aNode=new Node(0);
for (i=0; i<max; i++) {
aNode.setNum(i);
add (aNode);
aNode.setNext(null);
}
}
public void add(Node aNode) {
Node temp;
if(head==null)
head=aNode;
else {
temp=head;
while(temp.getNext()!=null)
temp=temp.getNext();
temp.setNext(aNode);
}
}
public void display() {
Node temp=head;
while(temp!=null) {
System.out.println(temp.getNext());
temp=temp.getNext();
}
}
}
public class Node {
private int num;
private Node next;
public Node (int n) {num=n; next=null;}
public int getNum() {return num;}
public void setNum(int n) {num=n;}
public void setNext(Node n) {next=n;}
public Node getNext() {return next;}
}
public class Driver {
public static void main(String args[]) {
List aList=new List();
aList.display();
}
}

The add relies on receiving a new Node with next being null. So move Node aNode = new Node(); inside the for-loop.
Some sanitary remarks.
(Unimportant) Use current instead of temp, or anything else.
Fields in classes are by default null/0/0.0/false.

Before I answer your question, here is a side note...
Im thinking its because the methods called before display simply modify a copy of head and not head itself.
This is NOT correct.
Here is why...
public void display() {
// Basically, this says, make temp a REFERENCE of head...NOT A COPY!!!!
Node temp=head;
while(temp!=null) {
System.out.println(temp.getNext());
temp=temp.getNext();
}
}
Now, to answer your question, the reason temp is null is because head is null. And the reason head is null is because you never initialize it.
From you constructor...
public List (){
int max=3;
int i;
// Here you're saying "set head to null".
// So when you call display, head is NULL. You MUST initialize this.
head=null;
Node aNode=new Node(0);
for (i=0; i<max; i++) {
aNode.setNum(i);
add (aNode);
aNode.setNext(null);
}
}

Look at this code from the constructor:
Node aNode=new Node(0);
for (i=0; i<max; i++) {
aNode.setNum(i);
add (aNode);
aNode.setNext(null);
}
You create one new node, and then keep trying to add that node to the list. You need the first line to be inside the for loop, so you create lots of nodes. After the constructor completes, your list only contains one node, with the value 3. Then later, in display():
System.out.println(temp.getNext());
You start by calling getNext() on the first node. Since there's only one node, getNext() returns null, which is what you print out. You should replace this line with
System.out.println(temp);
The error is nothing to do with the this keyword at all. You only need this.foo (when foo is some data member of your class) to disambiguate when you have a both a member and a local variable or parameter with the same name.

Related

Assign "this" to a reference variable in Java

I'm trying to used recursive method to complete the addLast method in a singly linked list, however, the code gives me a wrong output of list.size() = 2 and list.getFirst() = 5. The reason should be due to the line
SLList p=this;
It seems changing p reference changes "this" reference as well, which is not so logic to me. Could anyone give some details about this? Thx
public class SLList {
public class IntNode {
public int item;
public IntNode next;
public IntNode(int i, IntNode n) {
item = i;
next = n;
}
}
private IntNode first;
public SLList(int x) {
first = new IntNode(x, null);
}
/** Adds an item to the front of the list. */
public void addFirst(int x) {
first = new IntNode(x, first);
}
/** Retrieves the front item from the list. */
public int getFirst() {
return first.item;
}
/** Adds an item to the end of the list. */
public void addLast(int x) {
SLList p = this;
if (p.first. next == null) {
p.first.next = new IntNode (x, null);
}
else {
p.first = p.first.next;
p.addLast(x);
}
}
/** Returns the number of items in the list using recursion. */
public int size() {
/* Your Code Here! */
SLList p = this;
if (p.first == null) {
return 0;
}
else if (p.first.next == null){
return 1;
}
else {
p.first = p.first.next;
return 1 + p.size();
}
}
public static void main (String[] args) {
SLList list=new SLList (5);
list.addFirst(10);
list.addFirst(15);
list.addLast(17);
System.out.println(list.getFirst());
System.out.println(list.size());
}
}
The problem is nothing to do with the assignment of this. Nothing can change this. Period.
(But things can change the state of the object that this refers to.)
The real problem is in your implementation of the size method. Your size method is causing the list to change. It shouldn't. In your case, the change causes:
the size() method to return the wrong value
subsequent getFirst() calls to return the wrong value.
I won't say exactly where the bug, but you should be able to spot it yourself by a process of elimination. (Or if that fails, use a debugger and try to observe where the list is changing.)
There are bigger problems with your algorithms than you think. size() is incorrect. You can fix this if you realize that you need to count the number of IntNode objects in the list. Similarly all other methods need to manipulate IntNode objects.
SLList p = this;
p reference to the same SLList object. if you make any changes to 'p' then it will also happened to 'this', becuase of reference type (not value type).
Here in the statement
p.first = p.first.next;
the reference to the first is changed when you call 'addLast' method. You loss the reference to the first item.
If you remove the line
list.addLast(17);
in main method you will see the correct answer. The problem is with this method.
Change the method as follow and add the new method below.
/** Adds an item to the end of the list. */
public void addLast(int x) {
addLast(x, this.first);
}
private void addLast(int x, IntNode node){
if(node.next == null){
node.next = new IntNode (x, null);
}else {
node = node.next;
addLast(x, node);
}
}
Then you will not lose the reference to first item and now it works fine,
Problem in your implementation is addLast and size method are changing the value of field variable first.
It don't matter whether you assignthis to some variable or use directly.
Because assigning this to some variable does not create new this object but assign's reference to that variable.
So you should first copy value of first field variable to some local variable then iterate on it.In this way your first will not change.
Hint: Don't change the first variable reference.
Your addLast() and size() changes value of first which is wrong.
Problem is in this line.
p.first = p.first.next;

Getting nth node from a linked list

I have these code:
Class File:
public class LinkedListCustom<T> implements AbstractList<E>
{
private int numElements; private Node head, tail;
...
...
public Node(T element)
{
T data;
Node next, prev;
}
...
...
private Node getNthElem(int index)
{
Node temp = head;
for(int i=0; i<index; i++)
{
temp = temp.next;
}
return temp;
}
public T getNthVal(int index)
{
Node n = getNthElem(index);
return n.data;
}
}
Test file:
public class Tester extends TestCase
{
public void testGetN()
{
MyCustomLinkedList<Integer> myList = new MyCustomLinkedList<Integer>();
myList.add(1);
myList.add(2);
assertEquals("index 0 is 1", new Integer(2), myList.getNthValue(1);
}
}
However, this does not run properly. May I know what I could have done wrongly? If there is anything unclear I'll clarify it immediately.
EDIT: It compiles but there is a NullPointerException.
EDIT 2: SOLVED Sorry about the vague question and unclear code, but I just wanted to find out what I might not have implemented, and it turns out that #JaviFernandez was correct by asking whether I have implemented the add() method, which I didn't. I was just looking for an answer like that... Sorry if I have troubled anyone...
When you say getNthValue(1), this returns you the value at index 1, which is the second element since indices are 0-based. So in your linked list, you have the value 1 at index 0, and the value 2 and index 1.
private Node getNth(int index)
is missing a return:
return temp;

Head of 2 different linked lists getting changed to same value

I am creating a chained hash table that uses my own LinkedListclass to handle collisons. Here is where my issue is occuring: I start with an array of LinkedLists, my "hash table", intially set to null. When i wish to add a word, if the desired location is null, I create a new LinkedList, place it in that array index. I then create a new LinkedListNode and set the head of the new LinkedList to the new node.
My issue is occuring here: Whenever I set the head of my new LinkedList to my new LinkedListNode all of my previously created linkedlists also have their head changed to the new node.
My debugger shows that I am truly creating new linkedlists every time. I was afraid each array index was just pointing to a single array, but that is evidently not the issue. Below is all the relevant code
public class SetOfStrings {
private int arraySize;
private LinkedList[] mainArray;
private int totalCount;
//other methods here
public boolean add(String toAdd)
{
int hashToAdd = hash(toAdd);
int wasFound = contains(toAdd);
if(wasFound> 0)
{
return false; // means its already in the table
}
if(mainArray[hashToAdd]== null)
{
mainArray[hashToAdd] = new LinkedList();
ListNode newHead = new ListNode(toAdd);
mainArray[hashToAdd].setHead(newHead);
totalCount++;
return true;
}
ListNode currentHead = mainArray[hashToAdd].getHead();
ListNode newNode = new ListNode(toAdd);
newNode.setNext(currentHead);
mainArray[hashToAdd].setHead(newNode);
totalCount++;
return true;
}
public class ListNode {
private String thisString;
private ListNode next;
public ListNode(String setString)
{
thisString = setString;
next = null;
}
public class LinkedList {
private static ListNode head;
private static int count;
private static ListNode currentPosition;
// other methods here
public void setHead(ListNode newNode)
{ head = newNode;}
SUMMARY: Whenever I set the head of a Linked List to a new node, it changes the head of all my linked lists to point to the same new node
You are declaring your head as static. This means that it is shared between all instances of the LinkedList class. Removing the static keyword should fix the issue you described.

Head node of Linked List

So I was wondering how I could create a new empty linked list, using my class definition of List and node, with a first head node pointing to null without having to hold any integer value. The thing is I'm not allowed to change the given methods or add any to the definition, so whenever I create a list, in the constructor I'm not sure how I'm supposed to asign head to null. Here's part of the codes:
public class Node {
private Node next;
private int key;
Node(Node nxt, int keyValue) {
key = keyValue;
next = nxt;
}
Node getNext() {
return next;
}
int getKey() {
return key;
}
void putNext(Node nxt) {
next = nxt;
}
}
Class List
public class List {
private Node head;
List() {
head = new Node(null, -1); // arbitary value for head
head.putNext(null);
}
This is what I came up with. I just assign a random value to variable key in head node. But if I do this, it will kinda mess up with my later methods that used recursive like deletion or finding sum or find max, min, etc
Is there any other way around I can do to deal with this issue?
In an Empty Linked List Head is Just a pointer which points to Nothing. You dont need to worry about creating an object to which current head points. Just create a head pointer and assign it to NULL. When you are actually adding a Node assign the address of first node to Head. Thats it...
public class List {
private Node *head;
List() {
head = NULL;
}
}

Link List : initializing the header

So I'm working on a problem to print the nth element from the last of the list.
I have the method and a procedure figured out. This procedure finds the element.
public Node nth_element(Node head, int n){
// head to point to the first element in the list
// n is the element to be returned from the tail of the list
---do the function here---
}
Now when I'm in the main class and calling the above method. My Linked List class where the above method is declared initializes the head to null in its constructor.
How do i initialize the head?
This is my main class:
public class Main
{
static void main()
{
List l = new List() //initialize the list
//then i add the elements into the list using insert()
//display()
//now
**Node mynode = l.nth_element(head, value);**
// how do i initialize this head
}
In your self-defined linked list class List, you need to put head as the class field as
public class List {
private Node head = null;
// all method for List....
}
Then when you implement nthElement method, you don't have to use head as your first argument since it's already a class member and you can use it directly in your class methods. But if you do need to, then you can create a public method in List class:
public Node getHead() {
return head;
}
Your nthElement method will look like
public Node nthElement(Node head, int n) {
//implementation ...
}
Then in the main method, you can call nthElement like
Node mynode = l.nthElement(l.getHead(), value);
But make sure that your list is not empty. Otherwise, head is null.
Adding to #tonga's answer.
Your class List constructor should be something like:
private Node head;
public List(Node head)
{
this.head = head;
}
and then create your list
List l = new List(new Node(1));

Categories