File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Java in General and the fly likes Help Please Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "Help Please" Watch "Help Please" New topic
Author

Help Please

Kenyan Khan
Greenhorn

Joined: Feb 21, 2004
Posts: 2
Hey, i have the following code, it makes a map, but i keep getting a null pointer exception in my remove method. Anyone help me??? Pls
import java.lang.Math;
class Node{
Object key;
Object data;
Node next;

public Node (Object k, Object d, Node n){
key = k;
data = d;
next = n;

}//end of constructor
}// end of node class

public class Map{
public Map (int cap){

capacity = cap;
map = new Node[capacity];


int size=0;
int arraySize=0;
int placement = 0;
}//initialiser constructor

public Map () {

capacity = 11;
map = new Node[capacity];
int placement = 0;
int size = 0;
int arraySize =0;
}


private static int arraySize;
private static int capacity;
private static Node map[];
private static Node head;
private static Node oldHead;
private static int size;
private static int placement;



public static Object[] keys (){
System.out.println("KEYS METHOD ENTERED"); System.out.println();
Object arrayB[] = new Object[capacity];
int counterB = 0;
for (int counter = 0; counter < capacity ; counter++){

if (map[counter] != null){//list stored here

for (Node p = map[counter]; p != null; p = p.next){

arrayB[counterB] = p.key;


counterB++;

}//end of for

}//end of if

}//end of for





System.out.println("KEYS METHOD EXITED"); System.out.println();
return arrayB;

}//end of method
public static void remove(Object key){

for(int counter = 0; counter< capacity; counter ++){
// controls movement along array


if(map[counter].key!=null){

// 1) Node could be first in list
// 2) Further into the list
// 3) Not exist in this list, or the Map at all
// 1) If the node is first in the list:

if(map[counter].data == key){
// a) There are no following nodes after this one
// b) There is a list following on.

//a
if(map[counter].next == null){
map[counter]=null;
}
//b
if(map[counter].next != null){
map[counter] = map[counter].next;
}
}//end of if

else{//the node is further in
Node prev = map[counter]; System.out.println("Got here fucker");
for(Node q = map[counter]; q!= null; q=q.next){
//established that not first node, so started at next one
if(q.data == key){// must remove
if(q.next ==null){// then this is the last node in the list
prev.next = null; // node is removed by garbage collector
}
if(q.next!=null){//this is in the middle of a list
prev.next = q.next; // node removed
}
}
else{
prev = q; // other increments controlled by for loop
}

}//end of for
}//end of else



}//end of else

}//end of for loop

}

public static Object get (Object key) {
Object returnKey = "";//done to avoid null being printed out
for(int counter = 0; counter < capacity; counter ++){
if(map[counter] != null){ //there is a list here
for(Node scan = map[counter]; scan!= null; scan = scan.next){
if(scan.data == key){
returnKey = scan.data;
}
}//end of for loop for linked list

}//end of != null if
}//end of for loop



return returnKey;
}//end of get method
public static Object put (Object key, Object value){
Object toReturn = null;
/** System.out.println("PUT METHOD ENTERED"); System.out.println();
System.out.println("Current Key is "+key); */
placement = key.hashCode () % capacity;
/** System.out.println("placement " + placement);
System.out.println("Capacity " + capacity); */
if (map[placement] != null){//means we won't have to rehash as not adding to a new slot in array
System.out.println(" != null entered with key "+ key);
Node scanner = map[placement];
Node prev = scanner; //toReturn remains null, as nothing before it
for(scanner=map[placement]; scanner!=null; scanner = scanner.next){

if(scanner.next == null){//time to add
prev.next = new Node(key, value, null);
toReturn = prev.data;//this is where we added on
}
if(scanner.next!= null){//must keep going thorough the list, so move to scanner, done by for loop
//prev = scanner;
prev = scanner;
}

}

size++;
System.out.println(" != null if exited");
System.out.println();
}//end of if 1
if (map[placement] == null){//then we are about to add to a new section in the array, we must make sure we do not
// exceed the load factor



if ((arraySize + 1) < (Math.floor(capacity * 0.75))){//no rehash is needed
map[placement] = new Node (key, value, null);
arraySize++;
System.out.println(arraySize);
size++;
System.out.println(" Came to no rehash if in put method");

}//end of size 1 if
else{


Object tempKey = key; //don't want these to change during rehash
Object tempVal = value;
Map.rehash();
Map.put (tempKey, tempVal);
arraySize++;
System.out.println(" Came to rehash if");
}//end of if 2

}//end of if 2


return toReturn;
}//end of method
public static int size (){
return size;
}
public static void rehash (){
System.out.println("REHASH METHOD ENTERED"); System.out.println();
Object toBeHashed[] = Map.keys ();

size = 0; // no more objects in the array
int oldCapacity = capacity;
capacity = capacity * 2; arraySize =0;
Node temp[] = new Node[capacity];//because we cannot change the size of the old array


map =temp;
for (int j = 0; j < oldCapacity; j++)
{
if(toBeHashed[j]!=null){
Map.put (toBeHashed[j], toBeHashed[j]);
}
}
System.out.println("REHASH METHOD EXITED");
System.out.println();
}// end of rehash method



}// end of class

Tester Class:
public class A4Test {
public static void main( String a[] ) {
String s[]={"ape","bat","cat","dog","fox","gnu","hog","pig"};

Map m = new Map(3); // init capacity 3
for( int i = 0; i < s.length; i++ ){
m.put( s[i], s[i] );
}


Object b[] = m.keys();


m.remove("ape");

for( int i = 0; i < b.length; i++ )
System.out.print( ((String)m.get( b[i] )) + " ");
System.out.println(Map.size());
System.out.println();

}
}
THanks
Stefan Wagner
Ranch Hand

Joined: Jun 02, 2003
Posts: 1923

[Please use a better] subject [than] 'Please help'.
Make specific subjects! (At least: Map problem).
Use the code-Button and indentation to make your listing readable.
Describe it in brief words.
Shrink your code down to the very minimum.
[Edited for niceness by EJFH]
[ February 21, 2004: Message edited by: Ernest Friedman-Hill ]

http://home.arcor.de/hirnstrom/bewerbung
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24184
    
  34

Stefan,
Thanks for the helpful answers you've provided to other questions on JavaRanch! Do please remember, though, that the number one rule here is "Be Nice." We don't growl at JavaRanch members. It's fine to give people advice on how to post. It's not fine to make someone feel bad for posting in the first place. We have a very low tolerance for unkind behavior. Consider yourself warned.
I would have sent this as a private message, but your account isn't set up to receive them.


[Jess in Action][AskingGoodQuestions]
Michael Dunn
Ranch Hand

Joined: Jun 09, 2003
Posts: 4632
To the OP - don't know if this will help, but it runs OK if you comment out this line
m.remove("ape");
sever oon
Ranch Hand

Joined: Feb 08, 2004
Posts: 268
I'm afraid there are a number of problems with your code, too many for me to address here. But I'll begin with the first classes you listed. Let's take Node first...

This should be stored in a separate file called Node.java from your other class. Just a point of convention, not absolutely necessary, but it will help you keep things straight and get you used to following these conventions.
Next, the Map. This class you wrote has big problems. First, look at the constructors (reformatted for clarity):

Both of these constructors declare local variables, ints placement, size, and arraySize, that are set to zero and immediately go out of scope. If you deleted those lines, it would have no impact whatsoever on your code.
Also, rather than repeat code in different constructors, chain them so you only have to maintain one copy (if you see a change that needs to be made in the logical flow of that code, you don't want to have to go to every constructor you wrote and cut'n'paste the change).
Next, you are using static data and methods throughout the class that should not be static. The data:

The static keyword means that the data (and the methods you've applied it to) are associated with the class, not with *instances* of the class. It's essential for you to understand this to move forward. Picture a class, like your Node class, as a rubber stamp. When you say "new Node(...)", you are using that rubber stamp to stamp out a new object. Understand the relationship between objects and classes. An object is an instance of a class. Lassie is an instance of a Dog. Rover is an instance of a Dog. Red is an instance of a Color.
When you say use the static keyword, you're saying "I don't want this data to be attached to lassie, or rover, or red. I want it to be attached to the class--independent of any one instance. I don't think that's what you want...when you create a map by saying "new Map()", you want all that data to be associated with that map and that map instance alone. Static means that every member of the class shares access to that data:

Now if I write code that creates a bunch of Foo instances in some other part of the project:

After this code executes a.x is 1, b.x is 1, and Foo.s is 2. Note that I referred to s as being a member of the class by saying "Foo.s", not a.s or b.s (those are legal ways to access static data in Java, and unfortunately so because it confuses discussions like this one). All instances of Foo share that variable s. Each instance of Foo carries around its own x, though.
A few more things to consider. Don't carry around redundant data. I notice you have a member variable capacity. You can get this any time you want off of the actual Node[] simply by saying map.length. So this capacity int is unnecessary and only creates more work for you to maintain it. I noticed all those other member variables, head, oldHead, etc, are not used anywhere in your code. Get rid of them.
I admit I'm a little confused with the test app you provided. A map to me is a structure that takes one object, a key, and associates it with another object, a value. For instance, I could use a map to help me associate text and numerical representations:
Integer( 1 ) -> "one"
Integer( 5 ) -> "five"
If I say, get me the value associated with key Integer(10), I'd expect back a String that says "ten". Is this the intention of your map? If so, it doesn't make sense to set up associations between "ape" and "ape"--how do you know if you're map is functioning properly and handing back the value instead of the key?
In any case, go ahead and remove all the statics, put all your classes in different source files, and change your test app to make mappings that will clearly test your data structure. If you still get this NPE calling remove(), check out that first line in which you say map[counter].key != null. If map[counter] refers to a null entry in that array, trying to access key is going to raise an NPE.
So I think you can rewrite your Map class to be quite a bit smaller:

sev
[ February 25, 2004: Message edited by: sever oon ]
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Help Please