Arraylist of Hashtables of arraylist

K

Kamran Shafi

Hi,

I am creating an arraylist (say masterArrayList) of hashtables, where
each hashtable (say table) is of the format key=string, value =
arraylist of strings (say existing_strings). In a foreach loop I
retreive the corresponding hashtable from the masterArrayList and add
new strings to existing_strings after comparing the hashtable keys.

The problem is that when I add a new value to an existing_strings
arraylist it also add the new value to all other hashtables in the
masterArrayList.

Any idea what could be wrong?
 
A

Alberto Poblacion

Kamran Shafi said:
I am creating an arraylist (say masterArrayList) of hashtables, where
each hashtable (say table) is of the format key=string, value =
arraylist of strings (say existing_strings). In a foreach loop I
retreive the corresponding hashtable from the masterArrayList and add
new strings to existing_strings after comparing the hashtable keys.

The problem is that when I add a new value to an existing_strings
arraylist it also add the new value to all other hashtables in the
masterArrayList.

Any idea what could be wrong?

This hapens because you have added a reference to the same hashtable to
all the members of the ArrayList. That is, you have done something like
this:

ArrayList masterArrayList = new ArrayList();
Hashtable ht = new Hashtable();
for (int i=0; i<=n; i++)
{
masterArrayList.Add(ht);
}

You can fix it by doing a "new" for every element:

ArrayList masterArrayList = new ArrayList();
for (int i=0; i<=n; i++)
{
masterArrayList.Add(new Hashtable());
}
 
K

Kamran Shafi

This hapens because you have added a reference to the same hashtable to
all the members of the ArrayList. That is, you have done something like
this:

ArrayList masterArrayList = new ArrayList();
Hashtable ht = new Hashtable();
for (int i=0; i<=n; i++)
{
masterArrayList.Add(ht);
}

You can fix it by doing a "new" for every element:

ArrayList masterArrayList = new ArrayList();
for (int i=0; i<=n; i++)
{
masterArrayList.Add(new Hashtable());
}

Thanks for a quick response, here is my code:

ArrayList viafields = getListOfViaAttributes(record);
ArrayList viewfields = getListOfViewAttributes(record);
ArrayList ex_nodes;
Hashtable htable;

int i = 0;
foreach (string field in viafields)
{
if (!(HTableList.Count <= i))
{
htable = null;
htable = (Hashtable)HTableList;
//HTableList.Remove(htable);

if (!htable.Contains(field))
htable.Add(field, viewfields);
else
{
ex_nodes = (ArrayList)htable[field];
foreach (string node in viewfields)
{
if (!ex_nodes.Contains(node))
ex_nodes.Add(node);
}
}
//HTableList.Add(htable);
}
else
{
htable = new Hashtable();
htable.Add(field, viewfields);
HTableList.Add(htable);
}
i++;
}

Note that HTableList is a global and I am creating it in another
method as HTableList = new ArrayList();
Also ArrayList viafields and viewfields are created using new in their
respective methods.


Regards
Kamran
 
K

Kamran Shafi

This hapens because you have added a reference to the same hashtable to
all the members of the ArrayList. That is, you have done something like
this:
ArrayList masterArrayList = new ArrayList();
Hashtable ht = new Hashtable();
for (int i=0; i<=n; i++)
{
masterArrayList.Add(ht);
}
You can fix it by doing a "new" for every element:
ArrayList masterArrayList = new ArrayList();
for (int i=0; i<=n; i++)
{
masterArrayList.Add(new Hashtable());
}

Thanks for a quick response, here is my code:

ArrayList viafields = getListOfViaAttributes(record);
ArrayList viewfields = getListOfViewAttributes(record);
ArrayList ex_nodes;
Hashtable htable;

int i = 0;
foreach (string field in viafields)
{
if (!(HTableList.Count <= i))
{
htable = null;
htable = (Hashtable)HTableList;
//HTableList.Remove(htable);

if (!htable.Contains(field))
htable.Add(field, viewfields);
else
{
ex_nodes = (ArrayList)htable[field];
foreach (string node in viewfields)
{
if (!ex_nodes.Contains(node))
ex_nodes.Add(node);
}
}
//HTableList.Add(htable);
}
else
{
htable = new Hashtable();
htable.Add(field, viewfields);
HTableList.Add(htable);
}
i++;
}

Note that HTableList is a global and I am creating it in another
method as HTableList = new ArrayList();
Also ArrayList viafields and viewfields are created using new in their
respective methods.

Regards
Kamran- Hide quoted text -

- Show quoted text -


Thanks for the hint I got it write this time. I was not newing one of
the view arraylists inside the loop.
 
P

Peter Duniho

[...]
Note that HTableList is a global and I am creating it in another
method as HTableList = new ArrayList();

If I read your problem description correctly, you're not having trouble
with the hash tables per se, but rather with an ArrayList they contain
(though you seem to think there are more than one, Alberto is exactly
right: there's just one ArrayList).
Also ArrayList viafields and viewfields are created using new in their
respective methods.

But they are only created once in the method. So you keep adding the
same "viewfields" instance to all of your hash tables. So when you add
anything to that "viewfields" instance (which is called "ex_nodes"
where new additions are made), all of the hash tables appear to be
updated, because they all have copies of the same reference to the
single "viewfields" ArrayList you created.

I have a suspicion that the whole design is wrong, but that's between
you and your debugger. :) For the moment, I'll recommend two changes:

1) put your "viewfields" variable declaration and initialization
_inside_ the first foreach() loop if you want a new copy of the
ArrayList for each hashtable. This will cause a new "viewfields"
instance to be allocated for each "field" in "viafields", ensuring that
when you add a new "node" to the ArrayList that goes with the current
"field" in the current "htable", it only gets added in a single element
of a single hash table.

It won't fix any other basic design or implementation bugs that exist,
but at least the problem you're asking about will stop happening.

And then...

2) fix that first if() clause so that it reads "i <
HTableList.Count" instead of that ridiculously awful
"!(HTableList.Count <= i)".

Hope that helps.

Pete
 
K

Kamran Shafi

[...]
Note that HTableList is a global and I am creating it in another
method as HTableList = new ArrayList();

If I read your problem description correctly, you're not having trouble
with the hash tables per se, but rather with an ArrayList they contain
(though you seem to think there are more than one, Alberto is exactly
right: there's just one ArrayList).
Also ArrayList viafields and viewfields are created using new in their
respective methods.

But they are only created once in the method. So you keep adding the
same "viewfields" instance to all of your hash tables. So when you add
anything to that "viewfields" instance (which is called "ex_nodes"
where new additions are made), all of the hash tables appear to be
updated, because they all have copies of the same reference to the
single "viewfields" ArrayList you created.

I have a suspicion that the whole design is wrong, but that's between
you and your debugger. :) For the moment, I'll recommend two changes:

1) put your "viewfields" variable declaration and initialization
_inside_ the first foreach() loop if you want a new copy of the
ArrayList for each hashtable. This will cause a new "viewfields"
instance to be allocated for each "field" in "viafields", ensuring that
when you add a new "node" to the ArrayList that goes with the current
"field" in the current "htable", it only gets added in a single element
of a single hash table.

It won't fix any other basic design or implementation bugs that exist,
but at least the problem you're asking about will stop happening.

And then...

2) fix that first if() clause so that it reads "i <
HTableList.Count" instead of that ridiculously awful
"!(HTableList.Count <= i)".

Hope that helps.

Pete

Thanks Pete, I finally figured it out as I mentioned in my last mail.
And please forgive my ignorance as this is my first week into C#.
You have made me conscious. Why do you think the design is wrong?

Kam
 
K

Kamran Shafi

[...]
Note that HTableList is a global and I am creating it in another
method as HTableList = new ArrayList();

If I read your problem description correctly, you're not having trouble
with the hash tables per se, but rather with an ArrayList they contain
(though you seem to think there are more than one, Alberto is exactly
right: there's just one ArrayList).
Also ArrayList viafields and viewfields are created using new in their
respective methods.

But they are only created once in the method. So you keep adding the
same "viewfields" instance to all of your hash tables. So when you add
anything to that "viewfields" instance (which is called "ex_nodes"
where new additions are made), all of the hash tables appear to be
updated, because they all have copies of the same reference to the
single "viewfields" ArrayList you created.

I have a suspicion that the whole design is wrong, but that's between
you and your debugger. :) For the moment, I'll recommend two changes:

1) put your "viewfields" variable declaration and initialization
_inside_ the first foreach() loop if you want a new copy of the
ArrayList for each hashtable. This will cause a new "viewfields"
instance to be allocated for each "field" in "viafields", ensuring that
when you add a new "node" to the ArrayList that goes with the current
"field" in the current "htable", it only gets added in a single element
of a single hash table.

It won't fix any other basic design or implementation bugs that exist,
but at least the problem you're asking about will stop happening.

And then...

2) fix that first if() clause so that it reads "i <
HTableList.Count" instead of that ridiculously awful
"!(HTableList.Count <= i)".

Hope that helps.

Pete

Thanks Pete. And please forgive my ignorance as this is my first week
into C#.
You have made me conscious. Why do you think the design is wrong?

Kam
 
N

not_a_commie

What's wrong with the generics? List<> in place of ArrayList and
Dictionary<> in place of HashTable? I'd think this code would be
significantly more friendly with generics. You could go one step
farther and use the PowerCollections to eliminate one level.
 
P

Peter Duniho

[...]
Thanks Pete, I finally figured it out as I mentioned in my last mail.
And please forgive my ignorance as this is my first week into C#.
You have made me conscious. Why do you think the design is wrong?

I'm very suspicious of the apparent repetition of the contents of the
various hashtables. I admit, there's not enough code for me to make a
reliable determination, nor am I really all that interested in doing a
major code review of the overall design. All I can say is that it just
"feels" wrong.

The fact that you would add basically the same array list for each
field in the hashtable, and that you have code that takes all the
elements from one array list and ensures that they all exist in some
other array list, all of that strongly suggests that you really only
need one master list, but are for some reason maintaining multiple
copies. If not that, then there is likely still to be some better way
to maintain the data.

Like I said, it's not something I can really state unequivocably.
There is some possibility that I'm simply getting the wrong idea from
looking at some small portion of the overall code. But I can tell you,
if I had a development team member approach me with the code you've
posted here, I would immediately insist on reviewing the bigger
picture, to make sure that the overall design actually made sense (and
fix it, if my suspicion that it didn't turned out to be correct).

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top