hashcode

Map集合面试题

自闭症网瘾萝莉.ら 提交于 2020-03-16 18:30:51
有可能问道你都知道哪些常用的Map集合?   HashMap、HashTable、LinkedHashMap、ConcurrentHashMap。 Collection集合接口和Map接口有什么关系?   没关系,Collection是List、Set父接口不是Map父接口。 HashMap是线程安全的吗?线程安全的Map都有哪些?性能最好的是哪个?   HashMap不是线程安全的。线程安全的有HashTable、ConcurrentHashMap、SynchronizedMap,性能最好的是ConcurrentHashMap。 使用HashMap有什么性能问题吗?   使用HashMap要注意避免集合的扩容,它会很耗性能,根据元素的数量给它一个初始大小的值。 HashMap的数据结构是怎样的?默认大小是多少?内部是怎么扩容的?   HashMap是数组和链表组成的,默认大小为16,当hashmap中的元素个数超过数组大小*loadFactor(默认值为0.75)时就会把数组的大小扩展为原来的两倍大小,然后重新计算每个元素在数组中的位置。 怎么按添加顺序存储元素?怎么按A-Z自然顺序存储元素?怎么自定义排序?   按添加顺序使用LinkedHashMap,按自然顺序使用TreeMap,自定义排序TreeMap(Comparetor c)。

HashMap实现原理分析

三世轮回 提交于 2020-03-16 04:07:43
1 HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端。 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大。但数组的二分查找 时间复杂度小,为O(1); 数组的特点是: 寻址容易,插入和删除困难; 链表 链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N)。 链表 的特点是: 寻址困难,插入和删除容易。 哈希表 那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表。哈希表( (Hash table ) 既满足了数据的查找方便,同时不占用太多的内容空间,使用也十分方便。 从上图我们可以发现哈希表是由 数组+链表 组成的,一个长度为16的数组中,每个元素存储的是一个链表的头结点。那么这些元素是按照什么样的规则存储到数组中呢。一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。比如上述哈希表中,12%16=12,28%16=12,108%16=12,140%16=12。所以12、28、108以及140都存储在数组下标为12的位置。   HashMap其实也是一个线性的数组实现的,所以可以理解为其存储数据的容器就是一个线性数组。这可能让我们很不解,一个线性的数组怎么实现按键值对来存取数据呢

Object有哪些公用的方法?

空扰寡人 提交于 2020-03-15 09:03:32
Object是所有类的父类,任何类都默认继承Object。 public class Demo { public static void main(String[] args) { Object object = new Integer(1); Object object2 = new Integer(1); //final方法,获得运行时类型 Object classType = object.getClass(); //该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。 //这个方法在一些具有哈希功能的Collection中用到 int hashCode = object.hashCode(); //在Object中与==是一样的,子类一般需要重写该方法 System.out.println(object.equals(object2)); //唤醒在该对象上等待的某个线程 object.notify(); //唤醒在该对象上等待的所有线程 object.notifyAll(); //保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常 try { /* * 使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待

Java中创建对象的5种方式 &&new关键字和newInstance()方法的区别

浪尽此生 提交于 2020-03-13 18:48:47
转载:http://www.kuqin.com/shuoit/20160719/352659.html 用最简单的描述来区分 new关键字和newInstance()方法 的区别: newInstance: 弱类型。低效率。只能调用无参构造。 new: 强类型。相对高效。能调用任何public构造。 newInstance( )是一个方法,而new是一个关键字,其次,Class下的newInstance()的使用有局限,因为它生成对象只能调用无参的构造函数,而使用new关键字生成对象没有这个限制。 Class.forName("")返回的是类 Class.forName("").newInstance()返回的是object 作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如Spring去创建对象。然而这里有很多创建对象的方法,我们会在这篇文章中学到。 Java中有 5种 创建对象的方式,下面给出它们的例子还有它们的字节码: 使用new关键字 }→调用了构造函数 使用Class类的newInstance方法 } →调用了构造函数 使用Constructor类的newInstance方法 }→调用了构造函数 使用clone方法 } →没有调用构造函数 使用反序列化 } →没有调用构造函数 如果你运行了末尾的的程序,你会发现方法1,2,3用构造函数创建对象

HashMap的存储结构及原理

本小妞迷上赌 提交于 2020-03-13 09:22:55
1、HashMap的数据结构(HashMap通过hashcode对其内容进行高速查找,是无序的) 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端。 数组 :数组的存储区是连续的,占用内存严重,故空间复杂度非常大。但数组的二分查找时间度小;数组的特点:寻址easy,插入和 删除困难。 链表 :链表的储存区离散。占用内存比較宽松。故空间复杂度非常小,但时间复杂度大;链表的特点:寻址困难,插入和删除easy。 哈希表 HashMap 是由数组+链表组成。寻址easy,插入和删除easy。( 存储单元数组Entry[],数组里面包括链表 ) HashMap 事实上也是由一个线性的数组实现的。 所以能够理解为其存储数据的容器就是一个线性容器; HashMap 里面有一个内部静态类Entry,其重要的属性有key,value,next,从属性key,value 就能够非常明显的看出来 Entry就是 HashMap键值对实现的一个基础bean;也就是说HashMap的基础就是一个线性数组,这个数组就是Entry[]。Map里面的内容都保存 在Entry[]中; /** * The table, resized as necessary. Length MUST Always be a power of two. */ transient Entry[] table; 2

Java HashMap实现原理分析

末鹿安然 提交于 2020-03-13 09:20:18
参考链接:https://www.cnblogs.com/xiarongjin/p/8310011.html 1. HashMap的数据结构 数据结构 中有数组和链表来实现对数据的存储,但这两者基本上是两个极端。 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大。但数组的二分查找时间复杂度小,为O(1);数组的特点是:寻址容易,插入和删除困难; 链表 链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N)。 链表 的特点是:寻址困难,插入和删除容易。 哈希表 那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表。哈希表((Hash table)既满足了数据的查找方便,同时不占用太多的内容空间,使用也十分方便。   哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法—— 拉链法,我们可以理解为“ 链表的数组 ” ,如图:   从上图我们可以发现哈希表是由 数组+链表 组成的,一个长度为16的数组中,每个元素存储的是一个链表的头结点。那么这些元素是按照什么样的规则存储到数组中呢。一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。比如上述哈希表中,12%16=12,28%16=12,108%16=12,140%16=12。所以12、28

HashCode与Equals回顾

折月煮酒 提交于 2020-03-13 00:53:47
HashSet和HashMap一直都是JDK中最常用的两个类, HashSet要求不能存储相同的对象,HashMap要求不能存储相同的键 。 那么Java运行时环境是如何判断HashSet中相同对象、HashMap中相同键的呢?当存储了“相同的东西”之后Java运行时环境又将如何来维护呢? 在研究这个问题之前,首先说明一下JDK对equals(Object obj)和hashcode()这两个方法的定义和规范: (1) 在Java中任何一个对象都具备equals(Object obj)和hashcode()这两个方法 ,因为他们是在Object类中定义的。 equals(Object obj)方法用来判断两个对象是否“相同”,如果“相同”则返回true,否则返回false。 hashcode()方法返回一个int数,在Object类中的默认实现是“将该对象的内部地址转换成一个整数返回”。 (2)接下来有两个个关于这两个方法的重要规范(我只是抽取了最重要的两个,其实不止两个): 规范1 : 若重写equals(Object obj)方法,有必要重写hashcode()方法(避免不必要的麻烦) ,确保通过equals(Object obj)方法判断结果为true的两个对象具备相等的hashcode()返回值。说得简单点就是:“如果两个对象相同,那么他们的hashcode应该 相等”

HashMap实现原理分析

别说谁变了你拦得住时间么 提交于 2020-03-12 05:55:12
1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端。 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大。但数组的二分查找时间复杂度小,为O(1);数组的特点是:寻址容易,插入和删除困难; 链表 链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N)。 链表 的特点是:寻址困难,插入和删除容易。 哈希表 那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表。哈希表((Hash table)既满足了数据的查找方便,同时不占用太多的内容空间,使用也十分方便。   哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法—— 拉链法,我们可以理解为“ 链表的数组 ” ,如图:   从上图我们可以发现哈希表是由 数组+链表 组成的,一个长度为16的数组中,每个元素存储的是一个链表的头结点。那么这些元素是按照什么样的规则存储到数组中呢。一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。比如上述哈希表中,12%16=12,28%16=12,108%16=12,140%16=12。所以12、28、108以及140都存储在数组下标为12的位置。   HashMap其实也是一个线性的数组实现的

JDk1.8HashMap的源码分析

久未见 提交于 2020-03-10 20:27:38
JDk1.8HashMap的源码分析 HashMap用数组存放数据(总结) 调用键的hashCode()获得键的哈希值 用哈希值,计算一个下标值 i 新建Entry对象来封装键和值 Entry对象放在 i 位置 空位置,直接放入 有数据,依次用equals()比较是否相等 找到相等的,覆盖值 没有相等的,链表连接在一起 负载率、加载因子到0.75 新建翻倍容量的新数组 所有数据,重新哈希,放入新数组 jdk1.8 链表长度到8,转成红黑树 红黑树数据量减少到6,转回成链表 hashCode() Object的方法 Object中默认实现是使用内存地址,作为哈希值 如果对象作为键,放入HashMap,应该重写hashCode(),使用属性数据,来计算哈希值 HashMap中根据hash值求得index的 // 先用key求得hash值 static final int hash ( Object key ) { // h = key.hashCode() 为第一步 取hashCode值 // h ^ (h >>> 16) 为第二步 高位参与运算 int h ; return ( key == null ) ? 0 : ( h = key . hashCode ( ) ) ^ ( h >>> 16 ) ; } JDK1.8HashMap的put方法源码如下 /** * (1)

HashMap源码分析(jdk12)

房东的猫 提交于 2020-03-10 15:06:41
1. 初始化 ,hashMap初始化容量默认大小为16,默认负载因子为0.75F 一共有3个构造器 无参 带初始化容量 带初始化容量和初始化加载因子 前两个构造器都是调用第三个构造器。如果没有设置初始化容量或负载因子,以默认值创建。值得一提的是: 在调用构造器创建HashMap时不会立即创建容器,(在jdk1.8之后为 Node<K,V>[] table 用于存储键值对)。而是会在你第一次put元素的时候调用resize方法创建。 容器的大小必须为2的倍数。你在设置初始化容器大小时,如果输入的不是2的倍数,那会自动调整为最接近的大于输入值的2的倍数。主要在tableSizeFor这个方法实现。 该方法,先获取 输入数-1 的32位二进制前导零数目(这里-1理解一下就好了,不-1那对于恰好是2的倍数的,会扩大一倍)。-1无符号右移前导零数目位,这样就得到了最接近 输入数 的 2的倍数-1。最后判断n的大小, 如果n=-1表示cap=1,那就设置容量为1; 如果n>0,如果大于最大容量,那就设置为最大容量,否则设置为n+1。 hashMap有最大容量。2^30 链表长度阈值 当长度大于8时,会从链表转化为红黑树。至于为什么设置为8主要是理想状态下,设置合理的HashMap,根据泊松分布计算得到链表长度达到8的概率极低( 0.00000006)