Cannot access last linked list array element - java

I new in Java and trying to run some tests. I cannot use the .getLast() function as its showing error and also cannot seem to create the method. What am I doing wrong.
Here is my partial code. I am trying to create the getLast method which is failing.
Here is the error The type of the expression must be an array type but it resolved to ListOfNVersion03PartA.
*/
public class ListOfNVersion03PartA
{
private int thisNumber; // the number stored in this node
private ListOfNVersion03PartA next; // forms a linked list of objects
private final int nodeID; // a unique ID for each object in the list
private static int nodeCount = 0; // the number of list objects that have been created
/**
* #param num the value to be stored in this object
*/
public ListOfNVersion03PartA(int num)
{
thisNumber = num;
next = null;
++nodeCount;
nodeID = nodeCount;
} // constructor(int num)
/**
* #param num the multiple values to be stored in the list, in that order
*/
public ListOfNVersion03PartA(int [] num)
{
this(num[0]); // in this context, "this" invokes the other constructor
for (int i=1 ; i<num.length ; ++i)
insertLast(num[i]);
} // constructor(int [] num)
/**
* #return the number of elements stored in this list
*/
public int getListSize()
{
return nodeCount;
} // method getListSize
/**
* #return the last element in the list
*/
public int getLast()
{
int y = next[nodeCount-1];
return y;
} // method getLast
/**
* prints this object
*/
public void printNode()
{
System.out.print("[" + nodeID + "," + thisNumber + "]->");
} // method printListNode
/**
* prints the tail of a list
*/
private void printListTail()
{
printNode();
if ( next != null )
next.printListTail();
} // method printListTail
/**
* prints the contents of the list, in order from first to last
*/
public void printList()
{
printNode();
if ( next != null )
next.printListTail();
} // method printList
/**
* This method is NOT examinable in this test.
*
* prints the contents of the list, in order from first to last, and
* then moves the cursor to the next line
*/
public void printlnList()
{
printList();
System.out.println();
} // method printlnList
/**
* #return the number of times the element occurs in the list
*
* #param element the element to be counted
*/
public int countElement(int element)
{
return 999;
} // method countElement
/**
* #return the number of times the replacement was made
*
* #param replaceThis the element to be replaced
* #param withThis the replacement
*/
public int replaceAll(int replaceThis, int withThis)
{
return 999;
} // method replaceAll
/**
* #return a reference to the first object in the list that contains the parameter value, or null if it is not found
*
* #param findThis the value to be found
*/
public ListOfNVersion03PartA findUnSorted(int findThis)
{
// This algorithm is known as "linear search"
if ( thisNumber == findThis )
return this;
if ( next != null )
return next.findUnSorted(findThis);
return null;
} // method findUnSorted
/**
* #return the reference to the object containing the smallest element in the list
*/
public ListOfNVersion03PartA minRef()
{
// add and/or modify code to complete the method
ListOfNVersion03PartA minOfTail;
if ( next == null )
return this;
minOfTail = next.minRef();
if ( thisNumber <= minOfTail.thisNumber )
return this;
else
return minOfTail;
} // method minRef
/**
* Inserts an element in the last position. The pre-existing elements in the
* list are unaffected.
*
* #param newElement the element to be inserted
*/
public void insertLast(int newElement)
{
if ( next == null )
next = new ListOfNVersion03PartA(newElement);
else
next.insertLast(newElement);
} // method insertLast
} // class ListOfNVersion03PartA

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());

Algorithm on an ordered collection of strings

I have an assessment to do and I'm not good at programming. I can search for the algorithms and see how they are done, but in my case I have ordered collection of strings and somehow I have to use the get method.
I have these two classes that must not be changed:
public class SearchTest {
/**
* Test program for the Search class.
* Put whatever tests you like in the body of the method.
* #param args the command line arguments
* #throws java.io.IOException of error reading the input
*/
public static void main(String[] args) throws IOException {
// Don't change this line
final Search search = new Search();
// You can set this to any of the text files in the data folder
final FileStrings strings = new FileStrings("data/small.txt");
// add your tests here
System.out.println(search.longestWord(strings));
}
}
and
public class FileStrings implements StringList {
/** Underlying list of elements */
private final ArrayList<String> elements;
/** Number of calls to get() since the last call to resetCount() */
private int count;
/**
* Create a list containing the lines of a text file.
* #param fileName name of a text file of strings, in order
* #throws java.io.IOException on input error
*/
public FileStrings(String fileName) throws IOException {
elements = new ArrayList<>();
try (BufferedReader input = new BufferedReader(new FileReader(fileName))) {
String line;
while ((line = input.readLine()) != null) {
elements.add(line);
}
}
count = 0;
}
/**
* Returns the number of elements in this list.
* This method takes constant time.
* #return the number of elements in this list
*/
#Override
public int size() {
return elements.size();
}
/**
* Returns the element at the specified position in this list.
* This method takes constant time.
* #param i position in the list, between 0 and size()-1
* #return the element at the position i
*/
#Override
public String get(int i) {
count++;
return elements.get(i);
}
/**
* Reset the count field.
*/
public void resetCount() {
count = 0;
}
/**
* Getter for count.
* #return number of calls to get() since the last resetCount()
*/
public int getCount() {
return count;
}
}
And my first task is to find the longest word from the given file list.
This is my attempt(I know it's wrong, but can't follow examples, because the solutions I see use the array directly):
public class Search {
/**
* Returns the index of the longest string in the list.
* If there are several string of this length, the
* indexed returned is the that of the first.
* #param a list of strings, in ascending order
* #return position of an entry with the longest string in the list
*/
public int longestWord(StringList a) {
int i=0;
int longestWord=0;
String nextWord=a.get(i+1);
String previousWord=a.get(i);
while (i < a.size() ) {
if (nextWord.length()>previousWord.length()){
longestWord = i;
}
i = i + 1;
}
return longestWord;
}
The result should be "14", the world "because" is the 15th word and is the longest. I hope you can help me with this!
list of words
public class Search {
/**
* Returns the index of the longest string in the list.
* If there are several string of this length, the
* indexed returned is the that of the first.
* #param a list of strings, in ascending order
* #return position of an entry with the longest string in the list
*/
public int longestWord(StringList a) {
int length=a.get(0).length();
int i=0;
int longestWord=0;
while (i<a.size()){
if (a.get(i).length()>length){
length=a.get(i).length();
longestWord=i;
}
i = i + 1;
}
return longestWord;
}
managed to do it :P

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.

Java PhoneBook using ArrayList

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;
}

Categories