I have a need for hashmap-like functionality in Matlab, where the hashmap maps vectors to other vectors, and the number of vectors (ranging in the hundreds of thousands) is not known beforehand.
I tried Matlab's inbuilt Containers.Map, but that doesn't accept vectors as keys. Then I tried java.util.HashMap:
>> map = java.util.HashMap;
>> map.put(1:3,zeros(2,1));
>> map.get(1:3)
ans =
[]
So for some reason that doesn't seem to work, even though Java's HashMap should be able to map arrays to arrays.
The other option would be to keep two separate matrices, one for the keys and one for the values, and grow them incrementally. But I don't want really want to do that because of the pain in Matlab of growing things incrementally (even with block-size increments etc, e.g. here).
Questions: 1. Why doesn't Java's HashMap work here? 2. Any other approaches?
Thanks.
Here is a kludge that does what you want . . .
map = java.util.HashMap;
key = java.util.Vector;
matKey = 1:3;
for nn=1:numel(matKey)
key.add(matKey(nn));
end
map.put(key,zeros(2,1));
map.get(key)
..it is a starting point anyway.
I compared containers.Map with char keys (thanks to Andrew Janke) to java.util.HashMap with a wrapper object as key (as in this post, also thanks to Andrew Janke, and thanks to Rasman for pointing it out):
numvec = 10^5;
S = round(rand(numvec,10)*40);
matmap = containers.Map();
%pick a random vector
idx = ceil(rand()*numvec);
s1 = S(idx,:);
%put it in the map
matmap(char(s1)) = zeros(1,4);
for i=1:5*10^5
if i==10^3 tic; end %allow some time for getting up to speed before timing
%pick a random vector and put it in the map
idx = ceil(rand()*numvec);
s2 = S(idx,:);
matmap(char(s2)) = zeros(1,4);
%retrieve value of previous vector
v = matmap(char(s1));
%modify it randomly and put it back
v( ceil(rand()*4) ) = rand();
matmap(char(s1)) = v;
s1 = s2;
end
toc
javaaddpath('/Test/bin');
import test.ArrayKey;
javmap = java.util.HashMap;
idx = ceil(rand()*numvec);
s1 = S(idx,:);
%also convert value to ArrayKey so we can retrieve it by ref -- saves a put
%operation
javmap.put(ArrayKey(s1), ArrayKey(zeros(1,4)));
for i=1:5*10^5
if i==10^3 tic; end
idx = ceil(rand()*numvec);
s2 = S(idx,:);
javmap.put(ArrayKey(s2), ArrayKey(zeros(1,4)));
v = javmap.get(ArrayKey(s1));
v.x( ceil(rand()*4) ) = rand();
s1 = s2;
end
toc
Result:
>> testmaps
Elapsed time is 58.600282 seconds.
Elapsed time is 97.617556 seconds.
containers.Map is the winner.
Edit: I reran the test for numvec = 10^6 and everything else the same. containers.Map approach ran in 59 seconds. HashMap approach wasn't finished after 5 minutes and caused Matlab to become unresponsive.
Edit2: I also tried pre-allocating two separate matrices and find keys using ismember
. Performance was worse than HashMap.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With