[英]java hashmap keys
有什么理由为什么要使用String以外的任何东西作为哈希映射键? 看起来字符串在99%的时间内都足够好。 另外,您不必实现hashCode()和equals(Object o)。 谢谢
设想一下您想创建一个以用户的类型和名称为键的映射的情况。 在这种情况下,您最好编写一个由2个字段组成的类(并覆盖hashCode
和equals
)。 在这种情况下,使用单个String并尝试以某种方式将这2条信息组合为一个String会很麻烦并且容易出错。
就像Mark Elliot所说的那样,有时会有一个自然键,但没有自然的String形式。 为什么不使用它?
当您拥有方便的字符串形式或显而易见的字符串形式时,例如在处理数据库实体时,字符串就足够了。
但是,性能是另一个原因。
当然,如果要实现自定义键,则必须绝对确保它是不可变的。 正如垃圾神所说,这不仅是一种偏爱。 同样,可比性也无关紧要。
如果哈希图中有可变键,则可以完全破坏哈希图。
有时您想要一个对象而不是字符串
假设您有一个...的地图,假设一个客户和餐厅订单的地图(字典或其他哈希表)。
而不是
Customer c = new Customer("Bob");
Order o = new Order("Fries");
HashMap<string, Order> map = new HashMap<string, Order>();
map.put(c.Name, o);
您可以使用Customer对象访问所有内容
Hashmap<Customer, Order> map = new HashMap<Customer, Order>();
map.put(c, o);
现在,为什么您会喜欢呢?
也许在您的餐厅中,您在那个特定的夜晚有多个名为“ Bob”的客户,所以仅拥有名称的HashMap不再足够了。 您的Customer类将反映“ Bob”之间的差异,但是仅代表它们的字符串不会。
通过拥有客户的HashMap,您可以简单地更改客户类的哈希算法,一切都将正常运行(希望如此)。 如果您使用字符串,那么进行修改和唯一标识每个对象实例将不那么容易
字符串可以涵盖很多用例,但是使用更复杂的对象可以为您的代码提供更大的灵活性。 看到他们在美国刚刚宣布了NCAA大学篮球锦标赛的种子,我看看是否可以提出一个以锦标赛为主题的例子。
假设我想构建一个Hashmap来存储每个区域中的所有团队。 比赛分为四个地区:东,西,西南和东南。 您当然可以按照以下方式创建地图:
HashMap<String, List<Team>> teamsInRegions = new HashMap<String, List<Team>>();
但是,如果您已经有一个代表区域的对象怎么办? 您可能会这样做,因为每个区域都具有比名称更多的关联信息。 例如,我认为Region类可能看起来像:
public class Region {
private String name;
private Calendar firstRound;
private String firstRoundLocation;
private Calendar secondRound;
private String secondRoundLocation;
private Calendar thirdRound;
private String thirdRoundLocation;
....
}
你明白了。 如果HashMap是由String键入的,那么使用合理的Region.toString()方法并将其用作键当然可以逃脱,但是使用更复杂的对象将使您可以编写更灵活的代码。
尽管其他人可能会不同意,但有时我发现自己以某种无法预测的方式使用Google Maps,在其中调用HashMap.keySet()会给我提供一组包含大量信息的完全填充的复杂对象。 并且具有地图存在意味着我可以使用这些对象做出决定的其他地方也是如此。
例如,假设我想建立一个篮球比赛中所有比赛的所有位置的列表。 如果我的HashMap具有复杂的对象,那将很简单:
Set<Region> regions = myMap.keyset();
Set<String> gameLocations = new HashSet();
for (Region region : regions) {
gameLocations.add(region.getAllLocales());
}
等等。 因人而异。
好处:
1)字符串的不可变=> 线程安全 ,没有并发问题
2) 缓存 String的哈希码 (在JDK中为String类查找private int哈希)。 节省大量处理时间。
3) 字符串池,用于文字(重复使用字符串对象)或使用新运算符创建的内部字符串,以将其添加到池中
4) 安全性,没有人可以编辑密钥
5)等于和哈希码实现良好
下行:
1)字符串池存在将密码以明文形式暴露给有权访问Java应用程序内存的任何人的安全风险。 Java应用程序的核心转储,在/ tmp中生成内存转储,可能会给密码带来真正的威胁。
解决方案 :对于使用char []的密码,您可以通过将其设置为空白或其他任何可以降低公开密码的安全风险的字符来擦除修道院。
字符串可能是最常见的用例,但实际上取决于您要存储的内容。 您不希望仅将Key保留为String即可将Long转换为String。 只需使用数据类型建议的类型即可。 对于像Long这样的类型,您也不必实现hashCode / equals。 如果您正在考虑实现equals和hashCode的自定义类,无论如何都是一个好主意。 用Apache Commons的EqualBuilder来实现它也很简单。
我想您可以说String是“足够好”的,因为您可以将典型的键类型转换为String。 但是,相对于使用实键类型作为哈希表键的成本而言,这样做很昂贵。 考虑一下,例如,每次要将Integer
(或int
)用作哈希表键时,将其转换为String ...
另一点是,对键类型实现hashCode
和equals
很容易。 实际上如此简单,以至于像Eclipse这样的IDE都能够为您生成这两种方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.