Java相当于Perl的哈希值

由于超级灵活和方便,我一直在使用很多Perl哈希。 例如,在Perl中我可以执行以下操作:

$hash{AREA_CODE}->{PHONE}->{STREET_ADDR} 

我想知道如何用Java完成同样的事情,我想它与HashMap有关?

谢谢,

由于超级灵活和方便,我一直在使用很多Perl哈希。 例如,在Perl中我可以执行以下操作: $hash{AREA_CODE}->{PHONE}->{STREET_ADDR}我想知道如何用Java完成同样的事情,我想它与HashMap有关?

Java代码近似于以下Perl代码:

 my %hash; $hash{AREA_CODE}{PHONE}{STREET_ADDR} = "221B Baker Street"; printf "Street address is %s\n", $hash{AREA_CODE}{PHONE}{STREET_ADDR}; 

 HashMap>> hash = new HashMap>>(); hash.put("AREA_CODE", new HashMap>()); hash.get("AREA_CODE").put("PHONE", new HashMap()); hash.get("AREA_CODE").get("PHONE").put("STREET_ADDR", "221B Baker Street"); System.out.printf("Street address is %s\n", hash.get("AREA_CODE").get("PHONE").get("STREET_ADDR")); 

那不是特别的吗? 🙂

我说’近似’有很多原因。 其中之一就是在Java中,你只会因为想要在Java的下一行上完成相当于这个非常简单的Perl代码而受到极度中风的挫折:

 $hash{AREA_CODE}{PREFIX} = 800; 

如果你想要Perl在这样的事情上的灵活性和便利性,Java根本就不会给你。 更糟糕的是,它的支持者经常会因为表达这种愿望而责备你。

请参阅Map接口及其实现,特别是HashMap 。

请注意,Java没有Perl的自动生成 (方便但危险的function)

 hash.get("areaCode").get("phone").get("streetAdr") 

如果例如get(phone)返回null,则会抛出exception。 还要注意你不应该为具有固定名称(“属性”)的东西使用哈希,你应该用它的getter和setter来定义你自己的类。

首先,您的具体示例( $hash{AREA_CODE}->{PHONE}->{STREET_ADDR} ),使用硬编码字符串作为哈希键,在Java中并不像Michael Carman所指出的那样真正有用的数据结构 – 它应该存储为具有属性的类(并且说实话,它在概念上是一个糟糕的数据结构 – 像这样的数据更可能是一组手机,而不是手机的哈希)。

其次,假设你实际上是指$hash{$AREA_CODE}->{$PHONE}->{$STREET_ADDR} ,看起来每个人的Java代码到目前为止都没有实现通用的等效代码 – 代码都认为Java哈希是新初始化用于存储示例或完全填充以用于检索示例(换句话说,正如leonbloy的回答所指出的那样,缺少自动修复function)。

正确的代码mimiquing autovivification是:

 // This method will ensure that hash-of-hash-of-hashes structure exists of a given set of 3 keys. public HashMap>> autovivification_3rd_level ( HashMap>> hash , String AREA_CODE, String PHONE, String STREET_ADDR) { if (hash == null) { hash = new HashMap>>(); } if (!hash.contains(AREA_CODE) || hash.get(AREA_CODE) == null) { hash.put(new HashMap>()); } HashMap> AREA_CODE_hash = (HashMap>) hash.get(AREA_CODE); if (!AREA_CODE_hash.contains(PHONE) || AREA_CODE_hash.get(PHONE) == null) { AREA_CODE_hash.put(new HashMap()); } return hash; } //////////////////////////////////////////////////////////////////////////////////// // Equivalent to Perl's "$hash{$AREA_CODE}->{$PHONE}->{$STREET_ADDR} = value;" public Object put_3d_level_hash( HashMap>> 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>> 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); 

Java有哈希,但由于强类型,它们不像Perl中的哈希那么灵活。 多维哈希更难以使用。 在Perl中,您可以声明一个哈希并让autovivification按需创建嵌套哈希。

 my %hash; $hash{a}{b} = 1; 

在Java中,您必须预先声明它是哈希哈希。

 Map> hash = new HashMap>(); hash.put("a", new HashMap()); hash.get("a").put("b", new Integer(1)); 

对于每个额外的维度,您需要在声明中添加另一个Map嵌套。 除了单调乏味,这不是很好的。

如果哈希键是常量,为什么不能hash.getAreaCode().getPhone().getStreetAddr()呢? 请记住,您的getter或构造函数都需要处理默认值生成。

您可以轻松地对哈希进行子类化,以添加一个为您自动生成的方法。

来自: $hash{AREA_CODE}->{PHONE}->{STREET_ADDR}

要: hash.vivifyingGet(areaCode).put(phone, streetAddr)

假设我已经创建了哈希:

 /** * 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> hash = new HashMap>() { /** * Convenience method to get or create the next level of hash. * @param key the first level key * @return the next level map */ public Map vivifyingGet(Phone key) { if (containsKey(key)) { return get(key); } else { Map = hash = new HashMap(); put(key, hash); return hash; } } }; 

我在工作中错过了perl哈希,并使用哈希类做了一些丑陋的变通办法。

上周我有一个想法在一个PerlMap类中实现整个事情,它使用分隔符来访问对象,最重要的是Lists zu访问子集。

它适用于map.get(code:street:phone)map.put(code:street:phone,"123456789") 。 要获取phonenumber列表,只需使用map.getList(code:street)

我刚刚开始,但现在在我的项目中使用。 它没有复杂性的限制:-)你可以选择免费的分隔符。 我将整个内容放在http://www.jdeer.org下。 玩得开心。

如果你想要这种灵活性但仍然在JVM中运行,你可能会想要使用Groovy。 tchrist喜欢忽略Java强类型而不是像Perl或PHP这样的动态类型语言这一点 – 并且也喜欢忽略Java在运行时速度快一个数量级,但这只是我的“党派”,显然。