multidimensional array anxiety

May 11, 2006 at 2:40pm

multidimensional array anxiety

I’m trying to load an array like:

array[i][j][k][l] = this+that+the+other;

this, that, the, and other are all Atoms.

I get an error that I can’t use “+” on Atoms.

I’m certainly confused about all this, but I thought the concatenation was just used to load multidimensional arrays. Is that wrong? Is it actually trying to add them? I have been looking at all sorts of examples on the internet, but I can’t find anything terribly helpful. Can anyone explain to me how I’m supposed to load a 4D array?

J.

#25924
May 11, 2006 at 3:29pm

That’s absolutely correct. “+” is not defined on Atoms. I don’t see
what this error has to do with multidimensional arrays. Are you
trying to load an entire row at once?

nick rothwell — composition, systems, performance — http://
http://www.cassiel.com

#76946
May 11, 2006 at 4:00pm

Oh my God! If I’ve got your ear, Nick, I might actually try to explain my problem in a little more detail, since I don’t even know that a multidimensional array will do the trick (and I’ve been at this, literally, all day…)

I’ve got a bunch of flat database files. Just text. Each line is something like this:

20 3 -6 60|64 64 64 0|”/path/to/a/sample_C4.wav”

The first field describes basic musical attributes. The second, CC vales. The third, a path (obviously!). I’m trying to pull “ranges” out of these flat files, in the sense that I want to get into the ballpark, but not get one precise sample — if I use both fields 1 and 2, I get a precise mapping. I can get a ballpark using only the first field, which will give me colour, dynamic, interval, and pitch — which will be common to a number of samples. What I can’t seem to do is to find a good way of storing/recalling any entry that matches only the first field. Or, put another way, I need a collection that will map one key to many values.
If I hash entries by only the first field, then I lose a bunch of entries (the same hash just keeps getting over-written). If I hash by the full path, then it seems very awkward to work my way back to the first two fields… Does that make any sense? I know, this all sounds like very basic “one->many”, “many->many” database stuff, but it’s doing my head in!
Anyway, what I’m precisely trying to do is build a collection or stucture of some sort where I can get all entries/lines with a common field 1.

Any thoughts? Even if you can just point me in the right direction, I’d really appreciate it.

cheers,

J.

#76947
May 11, 2006 at 4:04pm

Create a HashMap object with the key you want and a heterogenous
ArrayList as the value.

wes

#76948
May 11, 2006 at 4:24pm

So my key is and my value is an ArrayList containing every line sharing that same … Holy crap. Could that have been any simpler? Sometimes, the harder you try, the wider the gulf between will and reason becomes… ouch.

Considering the format of field 1 (a string of 4 ints), would you use an equals(), or code something by hand to compare them? Just curious.

thanks, wes.

J.

#76949
May 11, 2006 at 5:08pm

No prob,
I would highly recommend reading these pages:
http://www.javapractices.com/Topic17.cjp

http://www.javapractices.com/Topic28.cjp

I used them for a MetaImage.java class. Here’s the code:
http://www.mat.ucsb.edu/~whsmith/EqualsHashExample.zip

You can do something similar with a lightweight class for your key object.

best,
wes

#76950
May 13, 2006 at 11:58am

So, I’ve got the following code, which is intended to check whether an entry exists. If not, add it (as an ArrayList).
If so, get the current ArrayList at that key, add the new
input to it, and put the whole thing back in the DB.

The problem is, I get multiple repetitions of the _last_
input, basically over-writing everything previously entered.
This is a familiar pattern, from creating an object at the
wrong point in the code (or re-using an object when I should
be creating a new instance), but I can’t see where I’m
messing up(?). Maybe it’s obvious…

private HashMap looseDB = new HashMap();

private void buildLooseDB(String shortAttrList, Atom[] CCList_fullpath)
{
if(!looseDB.containsKey(shortAttrList)) // if this shortAttrList isn’t in DB
{
ArrayList addLooseEvent = new ArrayList();
addLooseEvent.add(CCList_fullpath);
looseDB.put(shortAttrList,addLooseEvent); // add it to DB
} else { // otherwise,

extendLooseEventEntry = new ArrayList();
extendLooseEventEntry = looseDB.get(shortAttrList); // get the current entry, at this key
extendLooseEventEntry.add(CCList_fullpath); // add a new item (the input) to it
looseDB.put(shortAttrList,extendLooseEventEntry); // and put the revised entry back in DB
}
}

thanks in advance,

J.

#76951
May 13, 2006 at 12:31pm

For what it’s worth,

> extendLooseEventEntry = new ArrayList();
> extendLooseEventEntry = looseDB.get(shortAttrList);

this code (and the following few lines) suggests a misunderstanding.
Once you’ve assigned extendLooseEventEntry (the second time) it’s
pointing directly at the object in the HashMap, so (i) the first
assignment is superfluous and (ii) you don’t need to do the put().

nick rothwell — composition, systems, performance — http://
http://www.cassiel.com

#76952
May 13, 2006 at 9:29pm

Well, a “misunderstanding” doesn’t surprise me in the least; the documentation, and most of the literature on programming in general, seems to have been written for the phys-ed of word processors. “For what it’s worth”??? Well… a hell of a lot, really!!!

So, when I call “get”, am I just pulling out a reference to the object that’s still in the hashMap, not a copy of the object? I was always under the (mis)understanding that I was getting a copy that I had to do something with, then “put” back. If I can operate directly on the object, while it’s in the hashMap, life would certainly be alot simpler! Does this mean that I can call “add” on the ArrayList directly, just by referencing the object’s name? That would be really, really, really, cool.

Sorry if I sound like an idiot… though, to be quite honest, I don’t feel too badly about it. It makes perfect sense to think that if one stores something in a certain location, they’ll have to go “get” it if they want to do anything to it, and “put” it back when they’re done. Computer languages seem to demonstrate an almost diabolical ignorance of human common-sense, with what Lakoff & Johnson refer to as “conceptual metaphors” being violated with serial abandon (except, in many cases, with Max, which is why most of us are here!!!).

Anyway, if I’m in the ballpark now, please let me know. It would be a great help, as you can well imagine if you’ve read this far!

cheers,

J.

#76953
May 13, 2006 at 9:39pm

> So, when I call “get”, am I just pulling out a reference to the object that’s still in the hashMap, not a copy of the object? I was always under the (mis)understanding that I was getting a copy that I had to do something with, then “put” back. If I can operate directly on the object, while it’s in the hashMap, life would certainly be alot simpler! Does this mean that I can call “add” on the ArrayList directly, just by referencing the object’s name? That would be really, really, really, cool.

Yes, you can operate directly on the array list when you access it
from the HashMap and your changes will stay there. I’m not user this
ir proper JAVA code as it has been a while, but you’ll ge the idea

Ass u me hasMap has some items in it and that key accesses one of those items:

( (ArrayList)hashMap.get(key) ).add(newItem);

This will add a new item to the ArrayList associated with key in the HashMap.

best,
wes

#76954
May 13, 2006 at 11:45pm

well, well. definitely VERY good to know. Thanks, Wes.

J.

#76955
May 14, 2006 at 1:55pm

Okay, so I think I’ve got the HashMap and ArrayList stuff worked out. But I’m still getting the same results: every entry in the HashMap appears to be getting the _last_ input. The ArrayLists are the correct length (size()), but each Atom[] in the ArrayList is identical, and it’s always the last line in the DB file. This still suggests that the entire ArrayList is getting over-written with the last entry. I can’t see how this could be happening…

private HashMap looseDB = new HashMap();

private void buildLooseDB(String shortAttrList, Atom[] looseDBEntry)
{
if(!looseDB.containsKey(shortAttrList)) // if this shortAttrList isn’t in DB
{
ArrayList eventCandidates = new ArrayList(50);
post(shortAttrList +” “+looseDBEntry[0] +” ” +looseDBEntry[1] +” ” +looseDBEntry[2]);
eventCandidates.add(looseDBEntry); // add this input to the ArrayList
looseDB.put(shortAttrList,eventCandidates); // and put it in the DB.
} else { // otherwise,
looseDB.get(shortAttrList).add(looseDBEntry); // get the existing entry, and add this input
}
}

I’m checking it using this little method:

public void testOne(String shortAttrList, int index)
{
post(“size: ” +looseDB.get(shortAttrList).size());
Atom[] tester = (Atom[])looseDB.get(shortAttrList).get(index);
post(“” +tester[0] +” ” +tester[1] +” ” +tester[2]);
}

Sorry for being such a pain, but this is not making sense to me…

J.

#76956
May 14, 2006 at 5:45pm

On 13 May 2006, at 22:29, jbmaxwell wrote:

> I was always under the (mis)understanding that I was getting a copy
> that I had to do something with, then “put” back.

Nope. With the exception of the primitive types (int, bool, float
etc.) Java does everything by reference.

– N.

nick rothwell — composition, systems, performance — http://
http://www.cassiel.com

#76957
May 14, 2006 at 5:58pm

On 14 May 2006, at 14:55, jbmaxwell wrote:

> private void buildLooseDB(String shortAttrList, Atom[] looseDBEntry)

I don’t see anything obviously wrong with the code, so I’d have to
wonder where the Atom[] argument comes from, since you insert a
reference to it into the hash table.

Erm… you’re creating a hash table mapping String to ArrayList
[]>? Is this what you meant?

(I suggest dropping the unchecked dynamic type and qualifying all
occurrences of ArrayList.)

– N.

nick rothwell — composition, systems, performance — http://
http://www.cassiel.com

#76958
May 14, 2006 at 11:54pm

> Erm… you’re creating a hash table mapping String to ArrayList
> []>? Is this what you meant?
>

AAACK! Well yes, the mapping is what I was after, but your question pointed me in the direction of the problem; it was the Atom[] that was getting screwed up. I was creating the Atom[] itself outside of the loop that was calling this method, meaning that it was always the _same_ Atom[] being sent/referenced. So, I’m guessing the Atom[] was being over-written once it was already _in_ the ArrayList, which was already _in_ the HashMap(??). That at least makes sense, anyway. I knew it was something like that… just don’t know why it took me so long to find it.

Thanks,

J.

#76959

You must be logged in to reply to this topic.