A hash map works by taking a "key", hashing it, and using the resulting number to pinpoint a spot in memory to store the corresponding "value". There's also generally a method of dealing with collisions (where two different keys produce the same hash), but that's the basics.
With an array, you specify the numbers more directly - the data is generally stored contiguously in memory, at a point which can be determined by multiplying the size of the objects you're storing by the index of the object you want to store. Again, there are exceptions to this - the objects you're working with may not be of static size, but that's the basic idea.
Hash maps are rather inefficient in terms of RAM usage, because if you set aside a clump of memory for one, odds are it's going to have gaps in it due to the unpredictable nature of the hashes you're using to index into it. Arrays, on the other hand, tend to be exactly the size they need to be, and seldom much more.
On the other hand, finding a specific value in a hash map can be a lot faster than finding one in an array, under the right circumstances. Say you want to get information about "John Doe". In an array, you have to figure out the number of the index with that info, and if all you've got to go by is his name, then you'll be iterating through
all the indexes until you find the one you want. With a hash map, odds are the info is simply indexed against the string "John Doe" - the hash takes you right to the memory address you want.
Lua's tables, as Freack100 says, are both an array
and a hash map. You can treat them as an array (by using numeric indexes only). You can treat them as a hash map (by using just about any other sort of index). You can treat them as both at the same time (by using both methods to index into them). With LuaJ, the Java side of things is maintaining an array
and a hash map for each table you define, and it's figuring out which one to use depending on the context of your code. This is
not efficient in terms of execution speed, but such is the nature of a high-level language: You sacrifice efficiency for convenience, and tables are very,
very convenient.
In terms of when the array or the hash map will be referenced:
- #myTable (which returns the table's "length"), and the functions in the table API, deal with your table as an array. They entirely ignore its hash map side.
- The "pairs" iterator function gets all values from your table, those in the array, and those in the hash map. "ipairs" only checks the array.
- myTable.keyName can be used instead of myTable["keyName"] to get (most) string-based keys from the hash map of a table (and you actually get a minor speed boost for being specific in this manner, too).
Somewhat going off on a tangent, but just about every feature for dealing with a table as an array will assume that the highest index is the first one before a nil value is encountered. The only 100% reliable function that gets the highest index is table.maxn(), which for whatever reason was removed by Lua 5.2 (leaving a "pairs" loop as the only remaining method to determine it, short of ensuring there are no "gaps" in your indexes). ComputerCraft is currently still on Lua 5.1.