Java PhoneBook using ArrayList - java

Im trying to make a PhoneBook using array list but I'm not getting the right output here is my code, thank you for any help with this, the output I'm getting now is just a zero when i ask for the size, not seeming to add anyone, that is probably where the problem lies
import java.util.ArrayList;
public class Phonebook implements Directory
{
private ArrayList<Person> book;
public Phonebook ()
{
book = new ArrayList<Person>();
}
/**
* will return the number of entries currently entered in
* the <code>Directory</code>.
* #return - the number of valid entries in the <code>Directory</code>.
**/
public int size()
{
return book.size();
}
/**
* will display the entries currently entered in the <code>Directory</code>.
**/
public void listAll()
{
for(int i = 0; i < book.size(); i++)
{
System.out.println(book.get(i));
}
}
/**
* will add a new record to the <code>Directory</code> in alphabetical order
* if the name is not a duplicate entry. Otherwise no changes will be made.
* #param name - name of individual to be added to the <code>Directory</code>.
* #param number - phone number of the individual to be added.
* #return - true if the entry was added successfully, otherwise false.
**/
public boolean addPerson(String name, String number)
{
Person x = new Person (name, number);
if (checkPerson(name) == -1)
return false;
int index = 0;
while(index < book.size())
{
if((x.getName().compareTo((book.get(index)).getName())) < 0)
{
book.add(x);
return true;
}
index++;
}
return false;
}
public int checkPerson(String name)
{
int lo = 0;
int hi = book.size() - 1;
while(lo <= hi)
{
int half = (lo + hi) / 2;
if(name.equals(book.get(half).getName()))
return half;
if(name.compareTo(book.get(half).getName()) < 0){
hi = half - 1;}
else lo = half + 1;
}
return -1;
}
/**
* will remove an entry from the <code>Directory</code> if the name parameter
* is currently in the <code>Directory</code>. Otherwise no changes
* will be made.
* #param name - individual to be removed from the <code>Directory</code>.
* #return - true if the entry was successfully removed, otherwise false.
**/
public boolean removePerson(String name)
{
if (checkPerson(name) == -1)
return false;
book.remove(checkPerson(name));
return true;
}
/**
* will search the <code>Directory</code> to find out if the name passed in
* is currently in the <code>Directory</code>. If so, it will return the
* phone number associated with this person. Otherwise it will return null.
* #param name - name of individual to look up in the <code>Directory</code>.
* #return - the phone number if the name was found, otherwise null.
**/
public String lookUp(String name)
{
Person n = new Person (name, "999-9999");
int local = checkPerson(n.getName());
if(local == -1)
return null;
return book.get(local).getNumber();
}
/**
* will search the <code>Directory</code> to find out if the phone number
* is currently in the <code>Directory</code>. If so, it will return the
* name associated with this number. Otherwise it will return null.
* #param number - name of individual to look up in the <code>Directory</code>.
* #return - the name of the person if the number was found, otherwise null.
**/
public String lookUpNum(String number)
{
for(int i = 0; i <book.size(); i++)
{
if(number.equals(book.get(i).getNumber()))
return book.get(i).getName();
}
return null;
}
}
/**
* The Person class is a container class to hold the
* name and phone number of an individual. There are methods
* to access the name and number, and modify the name and number.
* Each name is stored in "Last, First" form to facilitate searching
* and sorting of persons. A private helper method is used to be
* sure that names entered in "First Last" form are converted to
* the proper format.
*/
public class Person implements Comparable<Person>
{
private String first;
private String last;
private String name; // Last, First
private String number;
/**
* explicit constructor, will store the first and last
* names, as well as the entire name in Last, First order
*
* #param na is the name of the individual
* #param nu is the phone number of the individual
*/
public Person(String na, String nu)
{
convert(na);
number = nu;
}
/**
* copy constructor, will make an exact copy of the parameter
*
* #param per is the <B>Person</B> to be duplicated
*/
public Person(Person per)
{
first = per.first;
last = per.last;
name = per.name;
number = per.number;
}
/**
* accessor method to return the name of <B>this Person</B>
*
* #return the name of the individual in Last, First order
*/
public String getName()
{
return name;
}
/**
* accessor method to return the phone number of <B>this Person</B>
*
* #return the phone number of the individual
*/
public String getNumber()
{
return number;
}
/**
* modifier method to set a new name for <B>this Person</B>
* The helper method convert() is called to handle the details
*
* #param the new name for the individual
*/
public void setName(String na)
{
convert(na);
}
/**
* modifier method to set a new phone number <B>this Person</B>
* just in case somebody needs to enter witness protection
*
* #param the new phone number for the individual
*/
public void setNumber(String num)
{
number = num;
}
/**
* accessor method that implements the <B>Comparable interface</B>
* based on the name field for <B>this Person</B>
* will return a positive number if <B>this</B> is greater than oth
* zero if <B>this</B> is equal to oth
* and a negative number if <B>this</B> is less than oth
*
* #return negative, zero, or positive int as per Comparable interface
*/
public int compareTo(Person oth)
{
return name.toUpperCase().compareTo(oth.name.toUpperCase());
}
/**
* accessor method to test if the instance data for <B>this Person</B>
* is equal to the instance data for oth
*
* #return true if names and numbers match, false otherwise
*/
public boolean equals(Person oth)
{
return name.toUpperCase().equals(oth.name.toUpperCase()) && number.equals(oth.number);
}
private void convert(String na)
{
if(na.indexOf(" ") == -1)
{
last = na;
first = null;
name = na;
}
else if(na.indexOf(",") != -1)
{
name = na;
first = na.substring(na.indexOf(",") + 2);
last = na.substring(na.indexOf(","));
}
else
{
first = na.substring(0, na.indexOf(" "));
last = na.substring(na.indexOf(" ") + 1);
name = last + ", " + first;
}
}
/**
* accessor method to return the instance data of <B>this Person</B>
* in a formatted String (24 character name field, followed by the number)
*
* #return name in Last, First order followed by the phone number
*/
public String toString()
{
String local = name;
if(name.length() < 8)
local += "\t";
if(name.length() < 16)
local += "\t";
local += "\t" + number;
return local;
}
}
public class client
{
public static void main(String[] args)
{
Phonebook nickBook = new Phonebook();
nickBook.addPerson("name lastname", "321-3256");
System.out.println();
nickBook.listAll();
System.out.println(nickBook.size());
}
}

Your addPerson method won't add the Person if the list is empty, since while (0 < 0) will be false, and the loop won't be entered :
int index = 0;
while(index < book.size())
{
if((x.getName().compareTo((book.get(index)).getName())) < 0)
{
book.add(x);
return true;
}
index++;
}
Beside that problem, book.add(x); will always add the new Person to the end of the List, which is not what you want. You should use book.add(index,x), assuming index is the location in which you wish to add the new Person.
Finally, if the new Person wasn't added inside the while loop, that means this Person should be the last Person on the List, so you have to add it to the end of the List after the loop.
A possible implementation :
public boolean addPerson(String name, String number)
{
Person x = new Person (name, number);
if (checkPerson(name) == -1)
return false;
int index = 0;
while(index < book.size())
{
if((x.getName().compareTo((book.get(index)).getName())) < 0)
{
book.add(index,x);
return true;
}
index++;
}
book.add(x); // this handles both the case of an empty List and the
// case in which the new Person should be the last Person
// on the list
return true;
}

Your function checkPerson is wrong. book.size() is 0 in the beginning and the hi results to -1 which means that it does not enter the loop. Besides that think about your half variable. It is possible that this results in another number than an integer which is not allowed if you are using this variable as an index for a query of the list.
public int checkPerson(String name)
{
int lo = 0;
int hi = book.size() -1;
while(lo <= hi)
{
int half = (lo + hi) / 2;
if(name.equals(book.get(half).getName()))
return half;
if(name.compareTo(book.get(half).getName()) < 0){
hi = half - 1;}
else lo = half + 1;
}
return -1;
}

Related

Array Loop is printing a reference instead of a string [duplicate]

This question already has answers here:
How to override toString() properly in Java?
(15 answers)
Closed 4 years ago.
I have been provided with an object and several methods to work with it. I am having a tough time printing the string that I am assigning to the variables. At the moment, I am unsure if I assigning new values at all and I am unable to print any values. Previous iterations have only printed references.
Question: Am I assigning new string values? How do I print a string with the given methods?
Here is the code I was provided
public class Team implements Comparable<Team> {
public String toString(String team, int wins) {
return team + ": " + wins;
}
// Data fields
private String name;
private int winCount;
Team() {
name = "Sooners";
winCount = 1;
}
Team(String inputName) {
name = inputName;
winCount = 1;
}
Team(String inputName, int inputWinCount) {
name = inputName;
winCount = inputWinCount;
}
// ----------------------------------------------------
// Getters and Setters
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name
* the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* #return the winCount
*/
public int getWinCount() {
return winCount;
}
/**
* #param winCount
* the winCount to set
*/
public void setWinCount(int winCount) {
this.winCount = winCount;
}
/**
* Increments the winCount variable by one for this Team
*/
public void incrementWinCount() {
winCount++;
}
/**
* This method allows you to check to see if this Team object has the same
* name as another Team object.
*
* This method allows you to use the contains method in ArrayList to see
* if any element in an array list has the same name as a specific Team.
*
* #param o
* the other Team being compared to.
*/
#Override
public boolean equals(Object o) {
return name.equals(((Team) o).name);
}
/**
* This method allows you to check to see if this Team object has the same
* name as another Team object
*
* #param otherTeam
* one team
*/
public boolean sameName(Team otherTeam) {
return name.equals(otherTeam.name);
}
/**
* This method allows you to check to see if this Team object has the same
* name as another Team object
*
* #param team1
* one team
* #param team2
* the other team
*/
public static boolean sameName(Team team1, Team team2) {
return team1.name.equals(team2.name);
}
/**
* This method allows you to sort an ArrayList of Team items using
* Collections.sort
*
* #param o
* the other Team being compared to.
* #return -1 if this Team item should come first, +1 if this Team item
* should come after the other, and 0 if this Team item is
* equivalent to the other.
*/
#Override
public int compareTo(Team o) {
if (this.winCount < o.winCount) {
return -1;
} else if (this.winCount > o.winCount) {
return 1;
}
return 0;
}
}
Here is my current code
Scanner scnr = new Scanner(System.in);
Random rando = new Random();
String name = "no";
int cycles = 0;
int value = 0;
int match = 0;
ArrayList<Team> teams = new ArrayList<Team>();
Team newTeam = new Team(name,1);
System.out.println("Welcome to the Advanced Sportsball Tracker!");
while (!name.equals("x")) // looping print statement
{ // x loop begins
System.out.println("Which team just won? (x to exit)");
match = 0;
cycles++;
name = scnr.next();
for (Team list : teams)
{
if (list.getName().equals(name)) // compares the name of the team to the input value
{
match++;
}
}
if (match == 0)
{
teams.add(newTeam);
}
}// x loop ends
System.out.print(newTeam.getName());
if (cycles == 1) // prints no data if user immediately exits
{
System.out.println("No data input");
}
if (cycles > 1)
{
System.out.println("Final Tally: "); // loop to print final Talley
for (Team list : teams) // FIXME
{
list.toString(list.getName(),list.getWinCount()); // makes a string out of the string and wincount of the team
}
What was the original code for the toString method they gave you? Did you add the parameters? A better way to do this would be to let the object use it's data fields inside of the method. Passing in the member variables in your for loop is unnecessary, and just bad code. Instead, you want to do something like this:
public String toString() {
return name + ": " + wins;
}
And in your loop, if you want to print the results, simply do this:
System.out.print(list.toString());

Parameters involving arrays (java)

Below I have programs I have worked on regarding an assignment
Card Class:
public class Card
{
// instance variables
private int value;
private String suit;
/**
* parameterized Card constructor -- gets called when an object of
* the Card class is instantiated sending a number as an argument -- it
* determines the value and suit of the card based upon the number received
* #param num a number that gets converted to a value between 1 and 13
* and a suit
*/
public Card(int num)
{
int suitNumber;
value = num % 13;
if (value == 0)
value = 13;
suitNumber = num / 13;
if (suitNumber == 0)
suit = new String("clubs");
else if (suitNumber == 1)
suit = new String("diamonds");
else if (suitNumber == 2)
suit = new String("hearts");
else if (suitNumber == 3)
suit = new String("spades");
else
suit = new String("ERROR");
}
/**
* getValue method -- returns what's stored in the instance variable value
* #return the state of the instance variable value
*/
public int getValue()
{
return value;
}
/**
* getSuit method -- returns what's stored in the instance variable suit
* #return a reference to a String that contains the state of the instance
* variable suit
*/
public String getSuit()
{
return suit;
}
/** equalValue method -- determines if the otherCard's value is the same
* as this card's value
* #param otherCard a reference to the Card object (assumes the object has been
* instantiated) to compare to this Card object
* #return true if the values are equal, false if the values are not equal
*/
public boolean equalValue(Card otherCard)
{
if (this.value == otherCard.value)
return true;
else
return false;
}
/**
* equalSuit method -- determines if the otherCards's suit is the same as
* this card's suit
* #param otherCard a reference to the Card object (assumes the object has been
* instantiated) to compare to this Card object
* #return true if the suits are the same, false if they are not
*/
public boolean equalSuit(Card otherCard)
{
if (this.suit.equals(otherCard.suit))
return true;
else
return false;
}
/**
* getPointValue method - this method returns the point value for the
* card - 10 for a face card, the actual value for cards 1 through 10
* #return the point value of the card
*/
public int getPointValue()
{
if (value > 10)
return 10;
else
return value;
}
/**
* equalCard method -- determines if the otherCard has the same value and
* suit as this card
* #param otherCard a reference to a Card object (assumes the object has been
* instantiated) to compare to this Card object
* #return true if the value and suits are the same, false if they are not
*/
public boolean equalCard(Card otherCard)
{
if (this.equalValue(otherCard) && this.equalSuit(otherCard))
return true;
else
return false;
}
/**
* isAFaceCard method -- determines if this card is a face card
* #return true if this card is a face card, false if it is not
*/
public boolean isAFaceCard()
{
if (value > 10)
return true;
else
return false;
}
/**
* toString method -- this method returns the state of the card object
* #return a reference to a String object that contains the values stored
* in the instance variables
*/
public String toString()
{
if (value == 1)
return (new String("Ace of " + suit));
else if (value == 11)
return (new String("Jack of " + suit));
else if (value == 12)
return (new String("Queen of " + suit));
else if (value == 13)
return (new String("King of " + suit));
else
return (new String(value + " of " + suit));
}
}
Now the trouble I am having is regarding this class
public class Hand
{
// instance variables
private Card[] cards;
private int numCards;
/**
* default Hand constructor --
* allocates an array that is capable of storing at most 10 Card references
* sets the number of cards to 0
*/
public Hand()
{
cards = new Card[10];
numCards = 0;
}
/**
* insertCard method --
* accepts a reference to the Card object to be stored in the next position in the
* cards array - checks to make sure the array isn't full
* #param theCard a reference to the Card object to be stored in the array
*/
public void insertCard(Card theCard)
{
if (numCards < cards.length)
{
cards[numCards] = theCard;
numCards++;
}
}
/**
* getCards method --
* makes a copy of the cards array and returns the address of the copy;
* the size of the array that is returned is based upon the number of
* cards currently in the hand
* #return a reference to the copy of the cards array
*/
public Card [] getCards()
{
Card [] cardsCopy = new Card[cards.length];
for(int i =0; i < cards.length; i++)
{
cardsCopy[i] = cards[i];
}
return cardsCopy;
}
/**
* replaceCard method --
* accepts a reference to a new Card object and the position in which
* the reference should be stored; the position is expected to be in the
* range 0 to (number of cards -1); position is validated to ensure that
* it is in this range
* #param pos the index where the card should be stored
* #param theCard the reference to the Card object to be stored in the array
*/
public void replaceCard(int pos, Card theCard)
{
}
/**
* searchCard method --
* accepts a reference to a Card to search for and determines whether
* or not that card exists in the hand
* #param theCard a reference to the Card to search for
* #return true if the card is found, false otherwise
*/
public boolean searchCard(Card theCard)
{
for(int i = 0; i < numCards; i++)
{
if(theCard.equalCard(cards[i]))
return true;
else
return false;
}
}
/**
* findNumFaceCards method --
* counts the number of face cards (ie. value of 11, 12 or 13) in the hand and
* returns the count
* #return the number of face cards in the hand
*/
public int findNumFaceCards()
{
int count =0;
for(int i =0; i < numCards; i++)
{
if(cards[i].getValue() >= 11)
count ++;
}
return count;
}
/**
* findLowCard method --
* finds and returns the position of the lowest card
* #return the index of the lowest card
*/
public int findLowCard()
{
int lowIndex = 0;
for(int i =0; i < numCards; i++)
{
if(cards[i].getValue() < lowIndex)
{
i = lowIndex;
}
}
return lowIndex;
}
/**
* replaceLowCard method --
* accepts a reference to a Card object and replaces the card
* having the lowest value with the new card
* #param theCard a reference to the Card object that will replace the
* lowest card
*/
public void replaceLowCard (Card theCard)
{
}
/**
* toString method --
* creates and returns a reference to a String with each of the card values
* on a separate line
* #return a reference to a String containing the state of the hand
*/
public String toString()
{
String str = "";
for(int i =0; i < numCards; i++)
str += "Card " + (i + 1) + ": " + cards[i] + "\n";
return str;
}
I am doing the replaceCard, searchCard and replacelowCard methods wrong(syntax errors). Most of these methods have the descriptions that my friend wrote to give me hints on what to write in the body. However, I mostly come up with errors on which code to use in the bodies.
For example, I have not yet learned how to search for a card in a array. I do know that there are two types of searching but I do not know if they are appropriate for this case.
For the replaceLowCard method, I am told that I will need the this.lowCard call to complete it.
And for the replaceCard method, I simply do not know what to do. Any help will be greatly appreciated.
(P.S: for this program, the deck is out of 52 cards).
I think an ArrayList is what you're looking for. It's dynamically sized, so all your insert-remove problems will be gone. Do something like this:
class Hand {
private List<Card> cards;
private int maxCards = 10;
public Hand() {
this.cards = new ArrayList<Card>();
}
}
And then you can do cards.add(...); to insert, cards.remove(...); to remove and so on... You can read more about ArrayLists here.
I hope this gives you a useful hint.

HashMap Difficulties

This is a school assignment. Overall this should read a text file, add words from it to a hash table. I've coded it out, but I'm testing it and it's giving me some problems. When I try to find the index of the object, it always returns -1, meaning it's saying the words aren't in the array even if they are. There are a few other problems as well. It's giving me a headache.
import java.util.Iterator;
import java.util.LinkedList;
public class MyMap<K,V> implements Iterable<MyMap.MyEntry<K,V>> {
int collision; // maintain the current count of collisions here.
int slots = 0;
int key = 0;
MyEntry<K,V> tempPair;
LinkedList<MyEntry<K,V>> [] bucketArray;
int keyMod;
/**
* Create a MyMap instance with the specified number of
* buckets.
*
* #param buckets the number of buckets to make in this map
*/
public MyMap(int buckets) {
slots = buckets;
bucketArray = (LinkedList<MyEntry<K,V>> [])new LinkedList[buckets];
}
/**
* Puts an entry into the map. If the key already exists,
* it's value is updated with the new value and the previous
* value is returned.
*
* #param key the object used as a key to retrieve the value
* #param value the object stored in association with the key
*
* #return the previously stored value or null if the key is new
*/
public V put(K key, V value) {
// don't forget hashcodes can be any integer value. You'll
// need to compress them to ensure they give you a valid bucket.
MyEntry<K,V> tempPair = new MyEntry<K,V>(key, value);
Word newWord = new Word((String)key);
keyMod = newWord.hashCode((String)key) % slots;
if ((bucketArray[keyMod]) == null){
LinkedList<MyEntry<K,V>> firstList = new LinkedList<MyEntry<K,V>>();
firstList.add(tempPair);
bucketArray[keyMod] = firstList;
return null;
}
else {
int indexNode = bucketArray[keyMod].indexOf(tempPair);
if (indexNode == -1) {
bucketArray[keyMod].add(tempPair);
collision += 1;
//System.out.println(indexNode );
return null;
}
else {
MyEntry<K,V> oldNode = bucketArray[keyMod].get(indexNode);
V oldValue = oldNode.value;
oldNode.value = tempPair.value;
//System.out.println(indexNode );
return oldValue;
}
}
}
/**
* Retrieves the value associated with the specified key. If
* it exists, the value stored with the key is returned, if no
* value has been associated with the key, null is returned.
*
* #param key the key object whose value we wish to retrieve
* #return the associated value, or null
*/
public V get(K key) {
//MyEntry<K,V> tempPair = new MyEntry<K,V>(key,value);
Word newWord = new Word((String)key);
int keyMod = newWord.hashCode((String)key) % slots;
if (bucketArray[keyMod] == null) {
return null;
}
else {
int temp = bucketArray[keyMod].indexOf(key);
if (temp == -1) {
return null;
}
else {
MyEntry<K,V> tempNode = bucketArray[keyMod].get(temp);
return tempNode.value;
}
}
}
/**
*
* I've implemented this method, however, you must correctly
* maintain the collisions member variable.
*
* #return the current count of collisions thus far.
*/
public int currentCollisions(K key) {
return collision;
}
/**
* Looks through the entire bucket where the specified key
* would be found and counts the number of keys in this bucket
* that are not equal to the current key, yet still have the
* same hash code.
*
* #param key
* #return a count of collisions
*/
public int countCollisions(K key) {
Word newKey = new Word((String) key);
int keyMod = newKey.hashCode((String) key) % slots;
if (bucketArray[keyMod].indexOf(key) == -1){
return bucketArray[keyMod].size();
}
return (bucketArray[keyMod].size()-1);
}
/**
* Removes the value associated with the specifed key, if it exists.
* #param key the key used to find the value to remove.
* #return the value if the key was found, or null otherwise.
*/
public V remove(K key) {
Word newWord = new Word((String)key);
//int keyMod = newWord.hashCode((String)key) % slots;
int tempNodeIndex = bucketArray[newWord.hashCode((String)key)].indexOf(key);
if (tempNodeIndex == -1) {
return null;
}
else{
tempPair = bucketArray[key.hashCode()].get(tempNodeIndex);
V returnValue = tempPair.value;
tempPair.value = null;
return returnValue;}
}
/**
* Returns the number of entries in this map
* #return the number of entries.
*/
public int size() {
int size = 0;
for (int i =0; i< bucketArray.length; i++){
size = bucketArray[i].size() + size;
}
return size;
}
/**
* Creates and returns a new Iterator object that
* iterates over the keys currently in the map. The iterator
* should fail fast, and does not need to implement the remove
* method.
*
* #return a new Iterator object
*/
public Iterator<MyEntry<K,V>> iterator() {
return null;
}
public static class MyEntry<K,V> {
K key;
V value;
public MyEntry(K k, V v) {
key = k;
value = v;
}
}
}
Here is the Word Class
/* The reason you can't extend String Class is because String is a final class and you can not have
* a subclass that might alter components of a final class. Since the word class would extend the
* String class, it would have the capability to change variables within the String Final Class.
*/
public class Word {
String word;
/**
* Creates a Word object representing the specified String
*
* #param w the String version of this word.
*/
public Word(String w) {
word = w;
}
/**
* Returns a hashcode for this Word -- an integer whose value is based on the
* word's instance data. Words that are .equals() *must* have the same hashcode.
* However, the converse need not hold -- that is, it *is* acceptable for
* two words that are not .equals() to have the same hashcode.
*/
public int hashCode(String word) {
int code = 0;
for ( int i =0; i<word.length(); i++){
code = word.charAt(i) + code;
}
return code; //word.hashCode();
//int hashCode = 0;
//for ( int i = 0; i<word.length(); i++) {
//hashCode = Math.abs(hashCode*13 + word.charAt(i));
//}
//System.out.println(hashCode);
//return hashCode;
}
/**
* Returns true if and only if this Word object represents the same
* sequence of characters as the specified object. Here, you can assume
* that the object being passed in will be a Word.
*/
public boolean equals(Object o) {
String passedIn = o.toString();
boolean returnValue = word.equals(passedIn);
return returnValue;
}
/**
* This method returns the string representation of the object.
* A correct implementation will return the String representation of the
* word that is actually being stored. ie., if you had a word object representing
* 'hi', it should return 'hi'
*/
public String toString() {
String thisString = word;
return thisString;
}
}
Here is the beginnings of my tester:
import java.io.*;
import java.util.*;
public class Tester<K,V> {
public static void main(String [] args) throws FileNotFoundException {
MyMap<String, Integer> pain = new MyMap<String, Integer>(3000);
Scanner s = new Scanner (new File("pg4.txt"));
while (s.hasNext()) {
String word = s.next();
Integer value = (Integer) pain.get(word);
if (value == null) {
pain.put(word, 1);
}
else {
value +=1;
pain.put(word, value);
}
}
s.close();
pain.put("the",1);
pain.put("the",5);
pain.get("the");
System.out.println("'the' gives this many collisions: " + pain.get("the") );
pain.remove("the");
System.out.println("'the' gives this many collisions: " + pain.get("the") );
}
}
indexOf uses equals for comparisons, so your calls to indexOf do not work. You need to implement equals for MyEntry.
public static class MyEntry<K,V> {
K key;
V value;
public MyEntry(K k, V v) {
key = k;
value = v;
}
#Override
public int hashCode() {
// (overriding hashCode
// just because we are overriding equals)
return ( key == null ? 0 : key.hashCode() );
}
#Override
public boolean equals(Object o) {
if(!(o instanceof MyEntry<?, ?>))
return false;
MyEntry<?, ?> that = (MyEntry<?, ?>)o;
return( this.key == null ?
that.key == null : this.key.equals(that.key)
);
}
}
If you don't do this, then you need to create your own indexOf method where you loop through the LinkedList yourself.
Your remove method does not actually do a removal, just set the value to null.
tempPair = bucketArray[key.hashCode()].get(tempNodeIndex);
V returnValue = tempPair.value;
tempPair.value = null;
More correctly it would be:
tempPair = bucketArray[key.hashCode()].remove(tempNodeIndex);
return tempPair.value;
As far as I can tell, you do not need the Word class at all. Your casting to String makes assumptions about what the type of K is, which is dubious for a generic class. (What if I have a MyMap<Long, Double>?)
You are only using it to get a hashCode which your K will already have (because hashCode is declared on java.lang.Object).
You could use hashCode from a temp MyEntry like I defined above or call it directly:
int keyMod = ( key == null ? 0 : key.hashCode() ) % slots;
To get your Word class working, you need to override hashCode correctly:
// now you can call hashCode() on a Word
// when a Word is passed in to MyMap as a key
#Override
public int hashCode() {
int code = 0;
// 'word' now refers to the instance variable
for ( int i =0; i<word.length(); i++){
code = word.charAt(i) + code;
}
return code;
}
// also implementing equals correctly, but your
// implementation in the question probably did
// not cause an error
#Override
public boolean equals(Object o) {
if(!(o instanceof Word))
return false;
String passedIn = ((Word)o).word;
boolean returnValue = word.equals(passedIn);
return returnValue;
}
Then you will be able to use a MyMap<Word, Integer>.
I found a few problems in my MyMap class where I wasn't constructing correctly. I found the error and fixed it. My tests were also causing errors. I corrected them. There were no problems in my Word Class. Once I corrected these the map constructed correctly, all methods worked.

NullPointerException when accessing array elements

I'm using BlueJ to create an array. The array is of 10 objects inherited from another class.
Now, my problem is that every time I try to find an object within the array (using the findInventoryItem, I get a java.lang.NullPointerException: null error. Now the "inventoryItem" object comes from another class. I am using inventoryItems as the actual array name. the objects that go into it are the inventoryItem of class InventoryItem
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
/**
* THIS IS THE MODIFIED VERSION OF THE ARRAY LIST MANAGER CLASS
*
* #author RAGEED A BASRAWI
* #version VERSION 1
*/
public class HomeInventoryManagerARRAYClass
{
private InventoryItem inventoryItem;
private InventoryItem[] inventoryItems;
/**
* Initialise the home inventory manager.
*/
public HomeInventoryManagerARRAYClass()
{
InventoryItem inventoryItem;
inventoryItems = new InventoryItem[10];
}
/**
* Add an inventory item to the list.
*
*/
public void addInventoryItem(InventoryItem inventoryItem)
{
Random random = new Random();
inventoryItems[random.nextInt(9 - 0 + 1) + 0] = inventoryItem;
}
/**
* Try to find an inventory item in the inventory list with the given partNumber.
*
*/
public InventoryItem findInventoryItem(int partNumber)
{
for(int index = 0; index < 9; index ++)
{
if (inventoryItem.getPartNumber() == partNumber)
{
return inventoryItem;
}
if (inventoryItem.getPartNumber() != partNumber)
{
System.out.println("The entry " + partNumber + " does not exist. Pleast try again.");
}
}
return inventoryItem;
}
/**
* Locate an inventory item with the given partNumber, and return how
* many of this item are in inventory. If the partNumber does not
* match any item, return zero.
*/
public int numberInInventory(int partNumber)
{
InventoryItem inventoryItems = findInventoryItem(partNumber);
if(inventoryItems != null)//There aren't too many ways to write a statement to be NOT NULL. Its kind of annoying... -___-
{
return inventoryItems.getQuantity();
}
else
{
return 0;
}
}
/**
* Return the total number of items in inventory.
*
*/
public int numberInInventoryList()
{
return inventoryItems.length;
}
/**
* Print details of all the home inventory items.
*/
public void printInventoryList()
{
int index = 0;
while(index < inventoryItems.length)
{
System.out.println(inventoryItem = inventoryItems[index]);
index ++;
}
}
public int totalNumberInInventory()
{
int index = 0;
int absoluteInventory = 0;
while (index < inventoryItems.length)
{
InventoryItem inventoryItem = inventoryItems[index];
absoluteInventory += inventoryItem.getQuantity();
index ++;
}
return absoluteInventory;
}
}
inventoryItems[random.nextInt(9 - 0 + 1) + 0] = inventoryItem;
if you initialize the array with the line above, how do you make sure that all elements of the array are initialized? It's generating a random number and doesn't guarantee all elements between 0 to 9 are initialized.
Remember that with this line:
inventoryItems = new InventoryItem[10];
you are initializing your array, not its elements. When running functions again each array's element you should be sure that you have initialized the element itself.
For example :
InventoryItem[i].getPartNumber()
this line of code should be executed before
InventoryItem[i] = new InventoryItem();
As #Jahoy has mentioned, it's likely that the elements in the array that you are accesing are null. It is essential firstly to check if an element exists in the first place.
Your FindInventoryItem function should be like this I think:
public InventoryItem findInventoryItem(int partNumber)
{
for(int index = 0; index < 9; index ++)
{
InventoryItem tempItem = inventoryItems[index]; // ADD THIS LINE HERE
if(tempItem != null)
{
if (tempItem.getPartNumber() == partNumber)
{
return tempItem;
}
if (tempItem.getPartNumber() != partNumber)
{
System.out.println("The entry " + partNumber + " does not exist. Please try again.");
}
}
}
// at this stage you've got no result, I dont really know what you want to return
return inventoryItem;
}

I need to create two more constructors, but Java won't let me

OK, I need to create three constructors as part of a project, one default, one general and one copy. I've managed to create a default constructor, but I can't create either the general or copy constructors because otherwise my code won't compile. Here is the code if anybody knows the answer:
package lab02;
import javax.swing.JOptionPane;
/**
* Stores the personal details of a friend.
*
* #author Keith Francis(11109971)
* #date 4-10-2012
*/
public class Friend {
private String firstName;// stores first name
private String surname;// stores surname
private String address;// stores address
private int age;// stores age in years
private int height;// stores height in cms
private String hairColourString;// stores hiar colour as a string
private boolean colourTrue = false;// hair colour value is not valid
public static final int BLACK = 0;
public static final int BROWN = 1;
public static final int BLONDE = 2;
public static final int RED = 3;
public static final int GREY = 4;
/**
* Default constructor sets everything to 0 or null, depending on type.
*/
public Friend() {
firstName = null;
surname = null;
address = null;
age = 0;
height = 0;
hairColourString = null;
}
/**
* Allows the first name to be edited
*
* #param first
* first name variable
*/
public void setFirstName(String first) {
firstName = first;
}
/**
* Retrieves first name
*
* #return first name to String
*/
public String getFirstName() {
return firstName;
}
/**
* Allows the surname to be edited
*
* #param last
* creates last name variable
*/
public void setSurname(String last) {
surname = last;
}
/**
* Retrieves the surname
*
* #return last name to string
*/
public String getSurname() {
return surname;
}
/**
* Allows the address to be edited
*
* #param place
* where the friend lives
*/
public void setAddress(String place) {
address = place;
}
/**
* Retrieves the address
*
* #return the address of the friend
*/
public String getAddress() {
return address;
}
/**
* Allows the age (in years) to be edited
*
* #param years
* the age in years
*/
public void setAge(int years) {
age = years;
}
/**
* Retrieves the age in years
*
* #return the age in years
*/
public int getAge() {
return age;
}
/**
* Allows the height in centimetres to be edited
*
* #param h
* height in centimetres
*/
public void setHeight(int h) {
height = h;
}
/**
* Retrieves the height in centimetres
*
* #return height in centimetres
*/
public int getHeight() {
return height;
}
/**
*
* #return String of the personal details of the friend
*/
#Override
public String toString() {
return ("First name is: " + firstName + "\nSurname is: " + surname
+ "\nAddress is: " + address + "\nAge is :" + age
+ "\nHeight is: " + height + "\nHair colour is: " + hairColourString);
}
/**
* Uses JOptionPanel to edit the friend's personal details
*/
void inputFriend()
{
//welcome message
JOptionPane.showMessageDialog(null,"Weclome",null,JOptionPane.PLAIN_MESSAGE);
//prompt to enter first name
String name1 = JOptionPane.showInputDialog("Enter the friend's first name.");
//calls setFirstName method
setFirstName(name1);
//prompt user to enter second name
String name2 = JOptionPane.showInputDialog("Enter the friend's surname.");
setSurname(name2);// calls setSurname method
//prompt user to enter address
String thisAddress = JOptionPane.showInputDialog("Enter the friend's address.");
setAddress(thisAddress);//calls setAddress method
//prompt user to enter age in years
String ageString = JOptionPane.showInputDialog("Enter the friend's age in years.");
int i = Integer.parseInt(ageString);
setAge(i);
//prompt user to enter height in centimetres
String heightString = JOptionPane.showInputDialog("Enter the friend's height in cenimetres.");
int j = Integer.parseInt(heightString);
setHeight(j);
//prompt user to enter hair colour
String hairColourInput = JOptionPane.showInputDialog("Select the friend's " +
"hair colour:\n 0 = Black\n1 = Brown\n2 = Blonde\n3 = Red\n4 = Grey");
while(colourTrue != true)//if hair colour is valid
{
if(
hairColourInput.equals("0"))
{ hairColourString = "Black";//hair is black
colourTrue = true;}//entry is valid
else if (hairColourInput.equals("1"))
{ hairColourString = "Brown";//hair is brown
colourTrue = true;}//entry is valid
else if (hairColourInput.equals("2"))
{ hairColourString = "Blonde";//hair is blonde
colourTrue = true;}//entry is valid
else if (hairColourInput.equals("3"))
{ hairColourString = "Red";//hair is red
colourTrue = true;}//entry is valid
else if (hairColourInput.equals("4"))
{ hairColourString = "Grey";//hair is grey
colourTrue = true;}//entry is valid
else {
JOptionPane.showMessageDialog(null,
"The number entered is invalid.", "Error",
JOptionPane.WARNING_MESSAGE);// warns user that entry is
// not valid
hairColourInput = JOptionPane
.showInputDialog("Select the friend's " +
"hair colour:\n 0 = Black\n1 = Brown\n2 = Blonde\n3 = Red\n4 = Grey");
}// user is asked to choose again until they enter a valid number
}
}
/**
*
* #param args
* Calls inputFriend method and prints out the final String using
* JOptionPane
*/
public static void main(String[] args) {
Friend friend = new Friend();
friend.inputFriend();// calls inputFriend method
JOptionPane.showMessageDialog(null, friend.toString()); // prints out details
}
}
Here is my attempt at a copy constructor:
public Friend(Friend aFriend) {
this(aFriend.getFirstName(), aFriend.getSurname(), aFriend.getAddress, aFriend.getAge, aFriend.getHeight);
and my attempt at the general constructor:
public Friend2(){
public static final int BLACK = 0;
public static final int BROWN = 1;
public static final int BLONDE = 2;
public static final int RED = 3;
public static final int GREY = 4;
}
What came up was that a class, interface or enum was expected when I inserted the constructor. Hope that helps.
Right, I've tried the copy constructor like this:
public Friend(Friend f) {
this(f.getFirstName(),f.getSurname(),f.getAddress(),f.getAge(),f.getHeight());
}
But I am getting a message saying that I don't have a suitable constructor.
UPDATE:general and copy constructors are now working. Thanks for your help.
you can overload the constructor like below:
cons1:
public Friend()
{
}
cons2:
public Friend(int arg)
{
}
cons3:
public Friend(String s)
{
}
copy cons:
public Friend(Friend f)
{
}
Your Friend2() constructor is wrong because it is actually a constructor for a Friend2 class. Constructors for a class should all have a method name that is the same as the class name. (constructors declarations look like method declarations named the same as the class but without specify a return type)
Your copy constructor is using this to call a constructor that does not exists. ( this(x,y,z) is calling the 3 argument version of the constructor)
What you want is something that looks like the following:
public class Friend
{
// snip
/**
* Default constructor sets everything to 0 or null, depending on type.
*/
public Friend()
{
firstName = null;
surname = null;
address = null;
age = 0;
height = 0;
hairColourString = null;
}
public Friend(Friend f) {
// copy constructor
}
public Friend(String fName, String sName, String address, int age, int height, String hair) {
// fill in stuff here
}
// snip
}
You need to overload your constructor. You cannot define a method with the same name and parameters. Look here for another reference:
Best way to handle multiple constructors in Java
http://www.java-samples.com/showtutorial.php?tutorialid=284
Overload your constructors, just make sure they have different signatures and it should compile fine. To keep it DRY, have the copy and general constructors use the default one by calling this().

Categories