Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > help with serializing a HashMap

Reply
Thread Tools

help with serializing a HashMap

 
 
Aryeh.Friedman@gmail.com
Guest
Posts: n/a
 
      11-17-2005
I have the following class that attempts to save a
HashMap<T1,ArrayList<T2>>

public class Roles
{
public Roles()
{
contributers=new
HashMap<Contributer,ArrayList<Role>>();
}
public void addRole(Contributer contributer,Role role)
{
ArrayList<Role> r=contributers.get(contributer);
if(r==null) {
r=new ArrayList<Role>();
} else r=contributers.get(contributer);
r.add(role);
contributers.put(contributer,r);
}
public ArrayList<Role> getRoles(Contributer contributer)
{
return contributers.get(contributer);
}
public void save()
{
FileUtils.serialize("contributers",contributers);
}
public void load()
{

contributers=FileUtils.deserialize("contributers", contributers.getClass());
}
public void reset()
{
contributers=new
HashMap<Contributer,ArrayList<Role>>();
}
public String toString()
{
String s=new String();
s+=contributers;
return s;
}
private HashMap<Contributer,ArrayList<Role>> contributers;
}

When I run it against the following test code I get the output below:
public class RolesTest extends TestCase
{
public void setUp()
{
mc=new MockContributer();
mr=new MockRole();
mrl=new ArrayList<MockRole>();
mcl=new ArrayList<MockContributer>();
mrl.add(mr);
mcl.add(mc);
}
public void testAdd() {
Roles roles=new Roles();
roles.addRole(mc,mr);
System.out.println(roles.getRoles(mc));
roles.save();
roles.reset();
roles.load();
System.out.println(roles.getRoles(mc));
}
private MockContributer mc;
private MockRole mr;
private ArrayList<MockContributer> mcl;
private ArrayList<MockRole> mrl;
}

Output:

[Name: mock role]
null

For reference here are the MockContributer, MockRole, Contributer,
Role, FileUtils and IOUtils (which FIleUtils.[de]serialize calls on):

public class MockContributer extends Contributer
{
public MockContributer()
{
super("aryeh");
}
private static final long serialVersionUID=0;
}

public class MockRole extends Role
{
public MockRole()
{
super("mock role");
}
private static final long serialVersionUID=0;
}

public abstract class Contributer implements Serializable
{
public Contributer(String id)
{
this.id=id;
}
public String getId()
{
return id;
}
public String toString()
{
String s=new String();

s+="authorId: "+id;

return s;
}
private String id;
}

public abstract class Role implements Serializable
{
public Role(String name)
{
this.name=name;
}
public String getName()
{
return name;
}
public String toString()
{
String s=new String();
s+="Name: "+name;
return s;
}

private static final long serialVersionUID=0;
private String name;
}

public class FileUtils
{
public static void serialize(String fname,Serializable obj)
{
FileOutputStream out=null;
try {
out=new FileOutputStream(fname);
} catch(FileNotFoundException e) {
throw new FileError(e);
}
IOUtils.serialize(out,obj);
try {
out.close();
} catch(IOException e) {
throw new FileError(e);
}
}
public static <T extends Serializable> T deserialize(String
fname,Class<? extends T> c)
{
FileInputStream in=null;
T obj=null;
try {
in=new FileInputStream(fname);
} catch(FileNotFoundException e) {
throw new FileError(e);
}
obj=IOUtils.deserialize(in,c);
try {
in.close();
} catch(IOException e) {
throw new FileError(e);
}
return obj;
}
}

public class IOUtils
{
public static void serialize(OutputStream out,Serializable obj)
{
try {
ObjectOutputStream stream=new
ObjectOutputStream(out);
stream.writeObject(obj);
} catch(IOException e) {
throw new IOError(e);
}
}
public static <T> T deserialize(InputStream in,Class<? extends
T> c)
{
try {
ObjectInputStream stream=new
ObjectInputStream(in);
T obj=c.cast(stream.readObject());
return obj;
} catch(IOException e) {
throw new IOError(e);
} catch(ClassNotFoundException e) {
throw new IOError(e);
}
}
}

 
Reply With Quote
 
 
 
 
zero
Guest
Posts: n/a
 
      11-17-2005
"(E-Mail Removed)" <(E-Mail Removed)> wrote in
news:(E-Mail Removed) ups.com:

> I have the following class that attempts to save a
> HashMap<T1,ArrayList<T2>>
>


<code snipped>

The first step when debugging should always be to exactly pinpoint the
problem. Print out the HashMap before you serialize it, after you
serialize it, before you deserialize, and after you deserialize. Before
you deserialize should be empty, all the rest should be the same. This
will help you see where the problem occurs: when adding items to the Map,
when serializing, or when deserializing. Run tests that show the data in
every stage of the program, that way you can be sure when it goes wrong.

I suspect the problem is when adding items. You'll probably need to
implement boolean equals(Object o) and int hashCode() in the Contributer
class.
 
Reply With Quote
 
 
 
 
Aryeh.Friedman@gmail.com
Guest
Posts: n/a
 
      11-17-2005
Actually no here is the test I was using (removed the two middle prints
to make the output/bug a little clearer):

public void testAdd() {
Roles roles=new Roles();
roles.addRole(mc,mr);
System.out.println(roles.getRoles(mc));
System.out.println(roles);
roles.save();
System.out.println(roles);
roles.reset();
System.out.println(roles);
roles.load();
System.out.println(roles);
System.out.println(roles.getRoles(mc));
}


Output:

[Name: mock role]
{authorId: aryeh=[Name: mock role]}
{authorId: aryeh=[Name: mock role]}
{}
{authorId: aryeh=[Name: mock role]}
null

 
Reply With Quote
 
zero
Guest
Posts: n/a
 
      11-17-2005
"(E-Mail Removed)" <(E-Mail Removed)> wrote in
news:(E-Mail Removed) ups.com:

> Actually no here is the test I was using (removed the two middle
> prints to make the output/bug a little clearer):
>
> public void testAdd() {
> Roles roles=new Roles();
> roles.addRole(mc,mr);
> System.out.println(roles.getRoles(mc));
> System.out.println(roles);
> roles.save();
> System.out.println(roles);
> roles.reset();
> System.out.println(roles);
> roles.load();
> System.out.println(roles);
> System.out.println(roles.getRoles(mc));
> }
>
>
> Output:
>
> [Name: mock role]
> {authorId: aryeh=[Name: mock role]}
> {authorId: aryeh=[Name: mock role]}
> {}
> {authorId: aryeh=[Name: mock role]}
> null
>


Ok, your problem is not with the serialization. As you can see on the
second to last line in your output, the HashMap gets read fine. Your
problem is that the rules.getRoles(mc) returns null.

Why?

To figure that out you first have to consider how objects are saved in a
HashMap. The hashMap uses the key's hashCode method to determine where
to put the object in its internal table. In your case, that's
MockContributer's hashCode function. However, you didn't implement
hashCode, so it's using the function inherited from Object. Object's
JavaDoc says "... typically implemented by converting the internal
address of the object into an integer"

So, what happens is that the object gets saved in a location determined
by its address. You then save the Map to disk, and delete the reference
to it. When you reload the Map, it - and all of its elements - have a
different address, and thus a different hashCode. You then try to get
back an object from the Map, but you're using an old reference - and an
old hashCode. The table entry in the Map corresponding to this old
hashCode is now empty, so you're getting a null object.

And the solution? If you don't actually need to use old references to
get items from the deserialized Map, you could ignore this problem, and
instead for example use an Iterator to get all the elements in the Map.
However, this may lead to problems later on, and is probably not
optimally performant.

The other, and better, solution would be to override the hashCode()
function of Contributer. This could be as simple as having an int
argument in Contributer. Other people here recently gave me some great
hints on how to write a good hashCode method. Have a look at:

http://groups.google.be/group/comp.l...owse_thread/th
read/32c74ea4ecc8e31f/6d7e56f773d37aa6
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Need help serializing data using C Durango C Programming 10 04-18-2012 02:09 PM
reuse HashMap$Entry (or HashMap in total) to avoid millions of allocations Vince Darley Java 4 03-02-2010 07:48 AM
java.util.Properties extending from HashMap<Object, Object> insteadof HashMap<String, String> Rakesh Java 10 04-08-2008 04:22 AM
Serializing a HashMap Tricia Williams Java 5 09-20-2005 05:14 PM
Serializing XML with JAXP - help needed Michael Java 1 02-22-2004 06:07 PM



Advertisments