Nicholas Kadaeux
Nicholas Kadaeux

Reputation: 2781

Generic Linked List of Objects (Java)

I'm pretty new to Java, with this being my second class (in College) using it. Towards the beginning of the semester, I made a simple class representing Zombies that holds their age, type, and name. Later on, I made a linked list of integers. Now, I need to make a generic linked list that can hold these 'Zombies'. I also have to make a menu that allows me to add, remove, count, and display 'Zombies'. I've been staring at this for hours, going through my book, and looking online for the answer to my problem. I can add and display these 'Zombies', but counting them in the list and trying to remove them simply has it tell me there's none with the parameters I entered. In other words, there might be a problem with how I compare the 'Zombies'. Here's my code. I understand it's a good 300 lines of code to look through... but i'm out of ideas.

Zombie.java

public class Zombie
{
private String zAge;
private String zType;
private String zName;

public Zombie(String zA, String zT, String zN)
{
    zAge = zA;
    zType = zT;
    zName = zN;
}

public void setZAge(String zA)
{
    zAge = zA;
}

public void setZType(String zT)
{
    zType = zT;
}

public void setZName(String zN)
{
    zName = zN;
}

public String getZAge()
{
    return zAge;
}

public String getZType()
{
    return zType;
}

public String getZName()
{
    return zName;
}

public boolean equals(Zombie zomb)
{
    if(zomb.getZAge() == zAge && zomb.getZType() == zType && zomb.getZName() == zName)
        return true;
    else
        return false;
}
}

LinkedBag.java

public class LinkedBag<E>
{
//Head node and number of nodes in bag
private Node<E> head;
private int manyNodes;

//Constructor
public LinkedBag()
{
    head = null;
    manyNodes = 0;
}

//Returns the number of nodes in the bag
public int getSize()
{
    return manyNodes;
}

//Returns the node that is at the head of the linked list
public Node<E> getListStart()
{
    return head;
}

//Adds a node to the beginning of the list
public void add(E element)
{
    head = new Node<E>(element,head);       //Creates a new node pointing to the head and sets the head of the linked bag to the new Node
    manyNodes++;        //Increments Node counter
}

//Counts the number of times Node [target] occurs within the bag
public int countOccurences(E target)
{
    int count = 0;      //Initializes incrementable counter

    if(head==null)      //Checks if bag is empty and returns null if bag is empty
        return 0;

    if(head.getData().equals(target))       //Checks if the head of the linked list is [target]
        count++;            //Increments counter

    Node<E> cursor = head;      //Sets temporary Node [cursor] to the same value and pointer as head

    while(cursor.getLink() != null)     //Loops until the next Node contains no value
    {
        if(cursor.getLink().getData().equals(target))           //Checks if the value of the next Node is [target]
            count++;                //Increments counter

        cursor=cursor.getLink();            //Cursor continues down linked list
    }

    return count;       //Returns incremented int [count], number of occurences of [target]
}

//Checks if Node [target] exists within the bag
public boolean exists(E target)
{
    if(head.getData().equals(target))       //Checks if the head of the linked list is [target]
        return true;

    Node<E> cursor = head;      //Sets temporary Node [cursor] to the same value and pointer as head

    while(cursor.getLink() != null)     //Loops until the next Node contains no value
    {
            if(cursor.getData().equals(target))     //Checks if current Node is [target] and returns true if true
                return true;

            cursor=cursor.getLink();        //Cursor continues down linked list
    }
            return false;       //Returns false if cursor goes through entire linked list and [target] isn't found
}

//Checks if Node [target] exists within the bag and removes the first occurence of it
public boolean remove(E target)
{       
    if(head==null)          //Returns false if bag is empty
        return false;

    if(head.getData().equals(target))   //If the head Node's data is [target]
    {
        head = head.getLink();      //Make the next Node the head
        manyNodes--;            //Decrements Node counter
        return true;            //Returns true, found [target]
    }

    Node<E> cursor = head;          //Sets temporary Node [cursor] to the same value and pointer as head

    while(cursor.getLink() != null)     //Loops until the next Node contains no value
    {
        cursor = cursor.getLink();      //Cursor continues down linked list

        if(cursor.getLink().getData().equals(target))   //If the next node's data is [target]
        {
            cursor.setLink(cursor.getLink().getLink());     //Sets current Node's link to the next Node's link, by passing the next Node
            manyNodes--;            //Decrements Node counter
            return true;            //Returns true, found [target]
        }
    }
    return false;           //Returns false, [target] not found
}
}

Node.java

public class Node<E>
{
private E data;
private Node<E> link;


public Node(E initialData, Node<E> initialLink)
{
    data = initialData;
    link = initialLink;
}

public E getData()
{
    return data;
}

public Node<E> getLink ()
{
    return link;
}

public void setData(E element)
{
    data = element;
}

public void setLink(Node<E> newLink)
{
    link = newLink;
}
}

And this is the menu file that the user interacts with ZombiesProj2.java

import java.util.Scanner;

public class ZombiesProj2
{
public static void main(String[] args) throws InterruptedException
{
    LinkedBag<Zombie> zBag = new LinkedBag<Zombie>();       //Linked bag to hold Zombie Objects
    String choice = "";

    Scanner input = new Scanner(System.in);

    while(!choice.equalsIgnoreCase("x"))
    {   
        //Menu
        System.out.println("\nSac de Zombi\n");
        System.out.println("S - Display size of bag");
        System.out.println("A - Add 'Zombie' to bag");
        System.out.println("R - Remove 'Zombie' from bag");
        System.out.println("F - Find 'Zombie' in bag");
        System.out.println("D - Display contents of bag");
        System.out.println("X - Exit");
        System.out.print("Enter Selection: ");

        //Input and Output
        choice = input.nextLine();

        if(choice.equalsIgnoreCase("s"))
        {
            System.out.println("\nSize = " + zBag.getSize() + "\n");
        }
        else if(choice.equalsIgnoreCase("a"))       //adds zombie
        {
            String zAge;
            String zType;
            String zName;

            System.out.print("How many years has this zombie ROAMED THE EARTH: ");
            zAge = input.nextLine();
            System.out.print("What type of zombie is it: ");
            zType = input.nextLine();
            System.out.print("What would you like to name this zombie: ");
            zName = input.nextLine();

            Zombie newZomb = new Zombie(zAge,zType,zName);
            zBag.add(newZomb);
        }
        else if(choice.equalsIgnoreCase("r"))       //removes zombie
        {
            String zAge;
            String zType;
            String zName;

            System.out.print("How many years has this zombie ROAMED THE EARTH: ");
            zAge = input.nextLine();
            System.out.print("What type of zombie is it: ");
            zType = input.nextLine();
            System.out.print("What is the name of the zombie: ");
            zName = input.nextLine();

            Zombie rZomb = new Zombie(zAge,zType,zName);

            zBag.remove(rZomb);
        }
        else if(choice.equalsIgnoreCase("f"))       //counts number of matching zombies
        {
            String zAge;
            String zType;
            String zName;

            System.out.print("How many years has this zombie ROAMED THE EARTH: ");
            zAge = input.nextLine();
            System.out.print("What type of zombie is it: ");

            zType = input.nextLine();
            System.out.print("What is the name of the zombie: ");
            zName = input.nextLine();

            Zombie fZomb = new Zombie(zAge,zType,zName);

            System.out.println("The " + zAge + " year old zombie type " + zType + " named " + zName + " occurs " + zBag.countOccurences(fZomb)+ " time(s)");
        }
        else if(choice.equalsIgnoreCase("d"))       //displays entire zombie 'bag'
        {
            Node cursor = zBag.getListStart();
            Zombie dZomb;
            while(cursor !=null)
            {
                dZomb = (Zombie)cursor.getData();
                System.out.print("[Zombie "+dZomb.getZAge()+" "+dZomb.getZType()+" "+dZomb.getZName()+"],");
                cursor = cursor.getLink();
            }
        }
        else if(!choice.equalsIgnoreCase("x"))  
        {
            System.out.println("Error: Invalid Entry");
        }
    }
}
}

Updated equals and hashCode

public boolean equals(Object obj)
{
    if(obj==null)
        return false;
    if(obj==this)
        return true;
    if(obj.getClass() != getClass())
        return false;

    Zombie zomb = (Zombie)obj;
    if(zomb.getZAge().equals(zAge) && zomb.getZType().equals(zType) && zomb.getZName().equals(zName))
        return true;
    else
        return false;
}

public int hashCode() { return 0; }

Upvotes: 3

Views: 30416

Answers (2)

Eric Jablow
Eric Jablow

Reputation: 7889

I know that because you are trying to learn programming you are writing your own linked list instead of using Java's LinkedList. However, there are a few things you have missed.

  1. Your equals method should have the same signature as that in Object Zombie.equals(Object). And, the first thing it should do is return false if the argument is not a Zombie.
  2. Whenever you write an equals method, you must also write a hashCode method. Look at most any example for details.
  3. Never use the equals operator for Strings. Always use the equals method. Replace zomb.getZAge() == zAge with zomb.getZAge().equals(zAge).
  4. Why is zAge a String? You can let it be some sort of number.
  5. There's no need to put 'Z' everywhere in your class. It's in a Zombie; your readers know. At work, I have colleagues who insist on repeating class names in all their variables.

This is not good code.

public class Document {
    private Long documentId;
    private String documentName;
    private String documentAuthor;
    private Date documentPublicationDate;
    // 10 more instance variables.
    // Constructors, accessors, other code.
}

And then they name variables of type Document as documentA, documentB, etc. How boring, repetitious, and redundant.

Upvotes: 3

7stud
7stud

Reputation: 48599

1) Why would you name a variable that contains the node count 'manyNodes' instead of 'nodeCount'. If you asked some random programmer what a variable named 'manyNodes' contained, do you think they would be able to guess? What if you asked some random programmer what the variable nodeCount contained? Do you think the random programmer could even guess the type of nodeCount? What about the type of 'manyNodes'?

2) How about trying something like this:

public void add(Node<E> element)
{
    if (head == null) {
        head = element;
    }
    else {
        tail.nextNode = element;
    }

    tail = element;
    nodeCount++;        //Increments Node counter
}


public class Node<E>
{
    private E data;
    private Node<E> nextNode;
}


public class LinkedBag<E>
{

    private Node<E> head;
    private Node<E> tail;
    private int nodeCount;   
}

//Constructor
public LinkedBag()
{
    head = tail = null;
    nodeCount = 0;
}

Upvotes: 0

Related Questions