leng - 1 等价于2n - 1,其值格式是:11111...,这样它与hash计算时,得到哈希桶下标,完全取决于hash,只要确保hash算法比较均衡,那么哈希表元素就会比较均衡了。
3、方便扩容
在扩容之后,所有的元素需要重新计算其所在哈希桶的位置。只要保证哈希桶容量是2的幂,其原先的元素要么保持不变,要么被移动到旧index+旧桶大小的位置上。
indexFor方法除了HashMap的实现方式,还有其他方式吗?跟HashMap的实现方式相比,有哪些不足?我们知道java中对哈希值的实现是根据每个对象的hashCode方法,而这个方法会可能返回42亿个可能性。而我们可以通过indexFor方法将这些42亿个可能性引入到16个哈希桶中。
除了HashMap内部的实现方式,还可以使用取模方法来达到效果。但要注意取模中负号的可能性!!!
static int indexFor(int hash) { if (hash < 0) { hash = -hash; } return hash % 16; }这种方式想比较HashMap原生的实现方式比较,就是低效。不仅仅是在这里计算时低效,而且还有可能会造成严重的哈希碰撞。
jdk1.8后,为什么要以8作为转化树的阙值?为什么要选择0.75作为负载因子?算法,在空间和时间的折中问题
五、相关应用我在项目遇到要依次匹配method然后引入对应的处理类。相关代码如下:
public class AppRestFactory { private static final String METHOD_WO_ = "";//方法名 /** * 工作中心人员的查询 */ private static final String METHOD_WORKCENTER_CONTACT = "getWorkCenterInfoByContact"; /** * 工作中心人员的查询 */ private static final String METHOD_TODOINFOLIST = "getTodoInfoList"; /** * 获取逻辑处理实例 * * @param method * @return */ public static AppRestService createService(String method) { if (METHOD_POSITION.equalsIgnoreCase(method)){ return SpringUtils.getBean(LocationServiceImpl.class); } if (METHOD_GETWOINFOLIST.equalsIgnoreCase(method)){ return SpringUtils.getBean(WorkOrderServiceImpl.class); } return null; } }这里就可能存在if、else查找效率问题。假设最后一个if才是要找method的话,那么程序的运行效率就会非常低。这还是未完成的情况,假设后期这个method被补充到上百个,那效率就会及其低下。这里其实就可以使用HashMap底层的哈希表的数据结构来优化。代码如下:
public class AppRestFactory { /** * 存储APP端方法method得映射关系 * todo:API数量确定后,固定HashMap得长度,防止hashMao扩容时,发生错误 */ private static final Map<String, Class> mapper = new HashMap<>(100); // 初始化method与其工作类得映射关系 static { // 添加退回物料的信息 mapper.put("addMaterialsReturnInfo", WoMaterialServiceImpl.class); // mapper.put("getBomAosProductsList", BomServiceImpl.class); } /** * 获取逻辑处理实例 * * @param method * @return */ public static AppRestService createService(String method) { return (AppRestService) SpringUtils.getBean(mapper.get(method)); } }原博客地址