Hi guys,

So for my next assignment I am required to, at some point, create a function that searches through an array of objects and sets a boolean value in a corresponding boolean array at the same position as the object in the object array, if that makes any sense.

I'll show you the code and where I'm having trouble:

ELEMENT ABSTRACT CLASS
:

package assignment.pkg2;

public abstract class Element {
    
    public String getClassName()
    { 
        String resultStr;
        
        int location;
        
        resultStr = this.toString();
        location = resultStr.indexOf('@');
        return resultStr.substring(0, location);
    }
    
    public abstract void readIn();

    
    public abstract void display();

    
    public abstract boolean equals(Element otherElement);
    
    public abstract Element clone(); [B]// Here I am told to add a @Override annotation for this statement and each subsequent clone function declarations in each class, why is this?[/B]

}

SUBSCRIBER CLASS:

package assignment.pkg2;

import java.util.Scanner;


public class Subscriber extends Element {
    private String name;
    private String url;
    
    private int adClicks;
    
    public Subscriber()
    {
        name = "";
        url = "";
        adClicks = 0;
    }
    
    public Subscriber(String aName)
    {
        name = aName.toUpperCase();
    }
    
    public Subscriber(Subscriber originalSub)
    {
        name = originalSub.name;
        url = originalSub.url;
        adClicks = originalSub.adClicks;
    }
    
    public String getName()
    {
        return name;
    }
    
    public String getUrl()
    {
        return url;
    }
    
    public int getAdClicks()
    {
        return adClicks;
    }
    
    public void setName(String aName)
    {
        name = aName.toUpperCase();
    }
    
    public void setUrl(String aUrl)
    {
        url = aUrl;
    }
    
    public void setAdClicks(int aAdClicks)
    {
        adClicks = aAdClicks;
    }
    
    public void readIn()
    {
        Scanner keyboard = new Scanner(System.in);
        
        System.out.println("Subscriber's name: ");
        name = keyboard.nextLine().toUpperCase();
        System.out.println("Subscriber's url: ");
        url = keyboard.nextLine();
        System.out.println("Subscriber's ad clicks: ");
        adClicks = keyboard.nextInt();
        
    }
    
    public void display()
    {
            System.out.println("\nSubscriber: " + name);
            System.out.println("URL: " + url);
            System.out.println("\n" + adClicks + " users have clicked on "
                    + "your ads.");
    }
    public boolean equals(Element otherSubscriber)
    {
        return name.equals(((Subscriber) otherSubscriber).name);
    }
    
    public Element clone()
    {
        Subscriber aClone = new Subscriber();
        aClone.name = name;
        aClone.url = url;
        aClone.adClicks = adClicks;
        
        return aClone;    
    }

}

APPLICATION CLASS:

package assignment.pkg2;

import java.util.Scanner;

public class Application extends Element{
   public String name;
   public String url;
   
   public int downloads;
   
   public Application()
   {
       name = "";
       url = "";
       downloads = 0;
   }
   
   public Application(String aName)
    {
        name = aName.toUpperCase();
    }
    
    public Application(Application originalApp)
    {
        name = originalApp.name;
        url = originalApp.url;
        downloads = originalApp.downloads;
    }
    
    public String getName()
    {
        return name;
    }
    
    public String getUrl()
    {
        return url;
    }
    
    public int getDownloads()
    {
        return downloads;
    }
    
    public void setName(String aName)
    {
        name = aName.toUpperCase();
    }
    
    public void setUrl(String aUrl)
    {
        url = aUrl;
    }
    
    public void setDownloads(int aDownload)
    {
        aDownload = downloads;
    }
    
    public void readIn()
    {
        Scanner keyboard = new Scanner(System.in);
        
        System.out.println("Application's name: ");
        name = keyboard.nextLine().toUpperCase();
        System.out.println("Application's url: ");
        url = keyboard.nextLine();
        System.out.println("Application's downloads: ");
        downloads = keyboard.nextInt();
        
    }
    
    public void display()
    {
            System.out.println("\nApplication: " + name);
            System.out.println("URL: " + url);
            System.out.println("\n" + downloads + " users have downloaded "
                    + "this application.");
    }
    public boolean equals(Element otherApplication)
    {
        return name.equals(((Application) otherApplication).name);
    }
    
    public Element clone()
    {
        Application aClone = new Application();
        aClone.name = name;
        aClone.url = url;
        aClone.downloads = downloads;
        
        return aClone;    
    }

}


ELEMENT SET CLASS
:

package assignment.pkg2;


public class ElementSet {
    private Element[] elementList;
    
    private boolean[] flagged;
    
    private int currentIndex;
    private int currentSize;
    
    private final int MAXSETSIZE = 100;
    
    public ElementSet()
    {
        elementList = new Element[MAXSETSIZE];
        flagged = new boolean[MAXSETSIZE];
        currentIndex = -1;
        currentSize = 0;
    }
    
    public boolean isMemberOf(Element anElement)
    {
        String paramClass = anElement.getClassName();
        String currClass;
        
        for (int i = 0; i < currentSize; i++)
        {
            currClass = elementList[i].getClassName();
            
            if (currClass.equals(paramClass))
            {
                if (elementList[i].equals(anElement))
                {
                    return true;
                }
            }
        }
        return false;
    }
    
    public boolean isFull()
    {
         return currentSize == MAXSETSIZE;
    }
    
    public boolean isEmpty()
    {
         return currentSize == 0;
    }
    
    public int size()
    {
         return currentSize;
    }
    
    public Element getCurrent()
    {
         // Local data ...
         int saveIndex = currentIndex;
       	
      	// Logic ...
         if (currentIndex == currentSize - 1)
         {
            // Recycle to beginning of list
            currentIndex = 0;
         }
         else
         {
            // Advance currentIndex to next object
            currentIndex++;
         }
         
      	// Return a reference to a clone of the current object
         return elementList[saveIndex].clone(); 
    }
    
    public int add(Element anElement)
    {
          // Logic ...
         if (currentSize == MAXSETSIZE)
         {
            return 0;  // set is full
         }
         else if (this.isMemberOf(anElement))
         {
            return -1; // it's already in there
         }
       
         // We will add a clone of anElement to
      	// the set.
         elementList[currentSize] = anElement.clone();
       
         // Increment currentSize.
         currentSize++;
      
         // Set currentIndex to object we just added if it was the
         // first object in the set. 
         if (currentSize == 1) currentIndex = 0;
      
         // We succeeded.
         return 1;
    }
     
    public void clear()
      {
       	// Clean up the memory associated with this object 
      	// while it is still in use.
         for (int i = 0; i < currentSize; i++)
         {
            elementList[i] = null;
         }
         
      	// Reset currentSize and currentIndex to empty set 
      	// values.
         currentIndex = -1;
         currentSize = 0;
      }
   
     public void display()
      {
         if (currentSize == 0)
         {
            System.out.println("There are no objects in the set. ");
         }
         else
         {
            System.out.println("Here are the objects in the set: \n");
            for (int i = 0; i < currentSize; i++)
            {
               elementList[i].display();
               System.out.println("\n");
            }
         }
      
      }
   

    public int flagIt(Element anElement) [B]//this is the function I am unsure is correct[/B]
    {
        String paramClass = anElement.getClassName();
        String currClass;
        
        for (int i = 0; i < currentSize; i++)
        {
            currClass = elementList[i].getClassName();
            
            if (currClass.equals(paramClass))
            {
                if (elementList[i].equals(anElement) && flagged[i] != false)
                {
                    System.out.println("Subscriber found, but has already been"
                            + " flagged.");
                    return 1;
                }
                
                else if (elementList[i].equals(anElement) && flagged[i] != true)
                {
                    System.out.println("Subscriber found and is now"
                            + " flagged.");
                    flagged[i] = true;
                    return 0;
                }
            }
        }
        System.out.println("Subscriber not found.");
        return -1;
    }
    
   /* public int unFlagIt(Element anElement)
    {
    
    }
    
    public void displayAllInClass(String theClassName)
    {
        
    }
    */
}

Some of the parts in the ElementSet class were given my our instructor, such as the "isMemberOf" function. When he explained what we needed to do with the "flagIt" functions I assumed it would be fairly similar to his "isMemberOf" function, but now I'm just unsure. Could anyone give me some guidance?

Also, when I attempt to call the function in main like this:

public class Assignment2 {

    public static void main(String[] args) {
        Subscriber sub1;
        sub1 = new Subscriber();
        
        sub1.flagIt();

    }
}

it returns an error "cannot find symbol" on the calling line; is the function not integrated into the other classes? Why would that be?

Thank you for any help!

Too long a question and many queries lumped together in a single post. You might want to post the minimum code required for presenting the question and add more code if requested. Plus, posting queries in code snippet as comments in a bad idea and I'm pretty sure those who had a look at this thread were wondering what the question was.

Anyways,

Here I am told to add a @Override annotation for this statement and each subsequent clone function declarations in each class, why is this?

@Override annotation enforces at compile time that the method on which this annotation is present either overrides a method of the super-class or implements a method of the implemented interface. In your case, you are overriding the `clone' method of your Element class. This annotation isn't mandatory but is quite helpful since it counters surprises in case you think you have "overridden" but actually you didn't.

class Super {
    public abstract void doIt();
}

class Sub1 {
    
    // notice the typo here; the compiler won't help you out with this one and
    // unless you are using an IDE, you won't be able to find it
    public void doIT() {}

}

class Sub1 {
        
    // will result in compile time error since you are not overriding the 
    // super-class doIt() method
    @Override
    public void doIT() {
    }

}

it returns an error "cannot find symbol" on the calling line; is the function not integrated into the other classes? Why would that be?

`flagIt()' is the method of ElementSet class and you are trying to invoke it on the Element sub-class hence the error. You need to first create an ElementSet out of your elements and then invoke flagIt() or any other method your assignment dictates. Your getClassName() logic also looks a bit suspicious. It is the responsibility of the `equals' method of your class to check for incompatible objects by using an `instanceof' check. Are you sure your TA wants you to use `getClassName()' ?

Bumpy Mc Bumperson.

Also, bumping the thread in just 7 hours = not good.

Thank you for the great help, and sorry for the cryptic post. I will try to edit it so it's easier to understand.

Also, I'm used to other message boards where, by 7 hours, my topic would be in archive status. Sorry for the early bump.

I will keep working on it, but the entirety of the flagIt() function is where I am having most trouble.

public int flagIt(Element anElement)
    {
        String paramClass = anElement.getClassName();
        String currClass;
        for (int i = 0; i < currentSize; i++)
        {
            currClass = elementList[i].getClassName();
            
            if (currClass.equals(paramClass))
            {
                if (elementList[i].equals(anElement) && flagged[i] != false)
                {
                    System.out.println("Subscriber found, but has already been"
                            + " flagged.");
                    return 1;
                }
                
                else if (elementList[i].equals(anElement) && flagged[i] != true)
                {
                    System.out.println("Subscriber found and is now"
                            + " flagged.");
                    flagged[i] = true;
                    return 0;
                }
            }
        }
        System.out.println("Subscriber not found.");
        return -1;
    }

My instructor said that it would be very similar to this function (at least for checking equality):

public boolean isMemberOf(Element anElement)
    {
        String paramClass = anElement.getClassName();
        String currClass;
        
        for (int i = 0; i < currentSize; i++)
        {
            currClass = elementList[i].getClassName();
            
            if (currClass.equals(paramClass))
            {
                if (elementList[i].equals(anElement))
                {
                    return true;
                }
            }
        }
        return false;
    }

Now, I think I need some input field for the user to find an individual subscriber/application object.

I am guessing I need to declare an object array in main and integrate some sort of binary search into the flagIt() method which then checks for equality and sets the boolean value for the new found object?

I'm sorry if I'm just throwing out guesses, but I am very unsure of how to implement something like that.

You still haven't answered the question I asked in my previous post:

Are you sure your TA wants you to use `getClassName()' ?

Regarding your suggestion, binary search works for sorted arrays and since there is no inherent order in your "element set", I'm not sure how it will help you out. You already have a a boolean array which keeps track of "flagging" the elements. Also, why does your ElementSet code hard-references "Subscriber" in the sysout text? Isn't it supposed to keep track of "generic" Elements rather than just the subscriber?

So my counter question would be, for what kind of sample code does your flagIt method fail? What does the following code print?

// untested code
public static void main(final String [] args) {
    final ElementSet set = new ElementSet();
    final Subscriber sub1 = new Subscriber("sub1");
    final Subscriber sub2 = new Subscriber("sub1");
    set.add(sub1);
    set.flatIt(sub2);
}

Your flagIt() method could use a bit of tuning but correctness first...

Edited 5 Years Ago by ~s.o.s~: n/a

You still haven't answered the question I asked in my previous post:


Regarding your suggestion, binary search works for sorted arrays and since there is no inherent order in your "element set", I'm not sure how it will help you out. You already have a a boolean array which keeps track of "flagging" the elements. Also, why does your ElementSet code hard-references "Subscriber" in the sysout text? Isn't it supposed to keep track of "generic" Elements rather than just the subscriber?

So my counter question would be, for what kind of sample code does your flagIt method fail? What does the following code print?

// untested code
public static void main(final String [] args) {
    final ElementSet set = new ElementSet();
    final Subscriber sub1 = new Subscriber("sub1");
    final Subscriber sub2 = new Subscriber("sub1");
    set.add(sub1);
    set.flatIt(sub2);
}

Your flagIt() method could use a bit of tuning but correctness first...

Yes, my instructor requires that we use the getClassName method, "the getClassName method is implemented once and for all in the Element class."

As for the printed text, I apologize. It should just be a generic "Object has been found" statement as I will be using that method for more than one class.

As for your sample code, here's the output:

run:
Subscriber found and is now flagged.
BUILD SUCCESSFUL (total time: 0 seconds)

It seems the equality checks out and it sets the flag appropriately (default value is false).

Once again, thank you for your help. It's greatly appreciated.

Once again, thank you for your help. It's greatly appreciated.

You are welcome; if your queries are answered, please mark the thread as solved so that it might help others who have similar needs.

Well, you said my flagIt method could use tuning.

Do you mind giving me some hints as to where I can improve it? I'd like to learn more efficient coding to help me in the future.

Edited 5 Years Ago by Syrne: n/a

First off, there is a equals() and hashCode() contract you must be aware of which states that if two objects are equal, they should have the same hashCode() which implies that if you are overriding equals method, you need to override the hashCode() method. In your case, it would be simply be a matter of returning the hashCode() of the `name' field. Not critical for your application, but something you must be aware of.

public class Application {
    public boolean equals(Object obj) {
        return this.name.equals(((Application)obj).name);
    }

    public int hashCode() {
        return this.name.hashCode();
    }
}

Second; in the flagIt method, it makes sense to first check for the already flagged status rather than checking for equality and classname since the flag check is very trivial as compared to the other two i.e. check for flagged == true first. Also, for booleans, you can leave off the equality check and just write if (flagged[i] && elementList[i].equals(anElement)) .

Also, as previously mentioned, using the getClassName() before equality checks is just wrong. This check needs to ideally go in the equals() method i.e.

public class Application {
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof Application)) {
            return false;
        }
        return this.name.equals(((Application)obj).name);
    }

    public int hashCode() {
        return this.name.hashCode();
    }
}

Also, hashCode() based containers are pretty good with existence checks i.e. if you use a secondary HashSet<Element> in your ElementSet class, you can get wicked fast existence checks since it internally uses the hashCode() to locate the element and equals() to resolve conflict. It might be a bit of an overkill for your assignment but something you must know of.

Edited 5 Years Ago by ~s.o.s~: n/a

This question has already been answered. Start a new discussion instead.