I\'ve been using a lot Perl hashes due to super flexibility and convenient. for instance, in Perl I can do the following:
$hash{AREA_CODE}->{PHONE}->{S
You can easily subclass your hash to add a method that'll autovivify for you.
From: $hash{AREA_CODE}->{PHONE}->{STREET_ADDR}
To: hash.vivifyingGet(areaCode).put(phone, streetAddr)
.
Assuming I've created the hash with:
/**
* A two-level autovivifying hashmap of X and Y to Z. Provides
* a new method #vivifyingGet(X) which creates the next level of hash.
*/
Map<AreaCode, Map<Phone, StreetAddr>> hash =
new HashMap<AreaCode, Map<Phone, StreetAddr>>() {
/**
* Convenience method to get or create the next level of hash.
* @param key the first level key
* @return the next level map
*/
public Map<Phone, StreetAddr> vivifyingGet(Phone key) {
if (containsKey(key)) {
return get(key);
} else {
Map<Phone, StreetAddr> = hash = new HashMap<Phone, StreetAddr>();
put(key, hash);
return hash;
}
}
};
First of all, your specific example ($hash{AREA_CODE}->{PHONE}->{STREET_ADDR}
), with hard-coded strings as hash keys, is not really a useful data structure in Java as Michael Carman pointed out - it should be stored as a class with attributes (and to be honest it's a bad data structure in concept - data like this is more likely to be an array of phones, not hash of phones).
Second, assuming you actually meant $hash{$AREA_CODE}->{$PHONE}->{$STREET_ADDR}
, it looks like everyone's Java code so far was NOT implementing a generic equivalent code - the code all assumed that the Java hash is newly initialized for storing example OR fully populated for retrieval example (in other words, as leonbloy's answer noted, is missing autovivification feature).
The correct code mimiquing autovivification is:
// This method will ensure that hash-of-hash-of-hashes structure exists of a given set of 3 keys.
public HashMap<String, HashMap<String, HashMap<String, Object>>>
autovivification_3rd_level (
HashMap<String, HashMap<String, HashMap<String, Object>>> hash
, String AREA_CODE, String PHONE, String STREET_ADDR) {
if (hash == null) {
hash = new HashMap<String, HashMap<String, HashMap<String, Object>>>();
}
if (!hash.contains(AREA_CODE) || hash.get(AREA_CODE) == null) {
hash.put(new HashMap<String, HashMap<String, Object>>());
}
HashMap<String, HashMap<String, Object>> AREA_CODE_hash
= (HashMap<String, HashMap<String, Object>>) hash.get(AREA_CODE);
if (!AREA_CODE_hash.contains(PHONE) || AREA_CODE_hash.get(PHONE) == null) {
AREA_CODE_hash.put(new HashMap<String, Object>());
}
return hash;
}
////////////////////////////////////////////////////////////////////////////////////
// Equivalent to Perl's "$hash{$AREA_CODE}->{$PHONE}->{$STREET_ADDR} = value;"
public Object put_3d_level_hash(
HashMap<String, HashMap<String, HashMap<String, Object>>> hash
, String AREA_CODE, String PHONE, String STREET_ADDR,
, Object value) {
hash = autovivification_3rd_level(hash, AREA_CODE, PHONE, STREET_ADDR);
return hash.get(AREA_CODE).get(PHONE).put(STREET_ADDR, value);
}
put_3d_level_hash(hash, AREA_CODE, PHONE, STREET_ADDR, obj);
////////////////////////////////////////////////////////////////////////////////////
// Equivalent to Perl's "$var = $hash{$AREA_CODE}->{$PHONE}->{$STREET_ADDR}"
public Object get_3d_level_hash(HashMap<String, HashMap<String, HashMap<String, Object>>> hash
, String AREA_CODE, String PHONE, String STREET_ADDR) {
hash = autovivification_3rd_level(hash, AREA_CODE, PHONE, STREET_ADDR);
return hash.get(AREA_CODE).get(PHONE).get(STREET_ADDR);
}
Object obj = get_3d_level_hash(hash, AREA_CODE, PHONE, STREET_ADDR);