treemapjava
Ⅰ java中,map分为哪些种类
您好,提问者:
Map:HashMap、TreeMap、Hashtable。
1、HashMap:线程不安全,键、值不允许为null。
2、Hashtable:线程安全,键、值允许为null。
3、TreeMap:线程不安全、键、值不允许为null,底层二叉树。
Ⅱ Java中HashMap和TreeMap的区别深入理解
HashMap底层是用数组做的,TreeMap是基于树做的
这么做的结果就是HashMap的数据在不停的添加的时候效率会比较低,而对于查找的效率是比较快的,TreeMap对于添加的效率是比较高的但是对于查找的效率要相对比较低一些
这里简单从底层说一下,我就不从具体的实现上说,只从数据结构和大致的原理上来补充一下我的答案。
HashMap这个类在存储的时候,首先根据key来计算机将要存储的key-value映射对存储在数组的什么位置上,当计算出位置后就把这个映射对存储到这个位置上。当读取的时候,首先根据key来计算出一个位置来,到数组的相应的位置上去读取数据,如果没有数据,则表示此Map中不存在该映射对,若存在则直接返回。说到这里就可以解释一下为什么对于不停地存储的效率相对比较低了,首先在初始化的时候对于数组的长度给了一个初始的长度,当往这里面添加数据达到一定的程度的时候就没法继续添加数据了,继续添加数据的冲突就会增大,或者没法添加数据(这里有一个衡量的量就是装填因子,是指这个数组中的添加的数据的个数和数组长度的比值,在java中比较合理的装填因子数是0.75),当数据添加到这个程度的时候不能不让用户继续添加数据吧,总得解决继续添加数据的问题啊,于是提出了解决方案,即开一个更大的数组,把当前上的每一个数据重新在更大的数组上计算位置,并把数据复制过去,这样完成的数组的扩大,看完这个我们知道,这个过程是很耗时的,所以说对于不停的存储数据时效率是比较低的。这里有没有一个稍微好一点的解决方案或者说不需要进行数组的扩大吗,我们能不能一开始在初始化的时候就把数组的空间开辟的足够大,这样就不用在存储的过程进行复制了,可以吗,答案是肯定的,java给我们提供了这个在初始化的时候的方式。但是,也是有问题的那就是我们的数据不够多,就会造成空间的浪费。有没有一个速度即快又不浪费空间的方式呢,解决方案也有一个,那就是在开始的时候我们就能很好的预测数据的规模,这样我们在开始的时候按照相应的规模进行初始化,这样就很好了,实际中我们是不能很好的预测这个规模的。于是对于这种情况提出了下一个解决方案TreeMap。
TreeMap是一个基于树的存储结构,学过数据结构的应该知道,树的实现方式是基于指针实现的,在Java中是用引用模拟实现的,这里大家都知道,其实树的读取效率并不低,这里是相对于数组的顺序查找来说的,但是与HashMap的查找方式相比就有了差距,HashMap是上来先问你在哪,直接就去取数据了,TreeMap需要遍历,也就是需要挨个询问你是我要的东西吗,对比一下,是就返回,不是就继续查找,于是查找的效率就低了,但是它解决了HashMap数组扩大的时候的效率问题,就是新添加的数据可以往里面添加,不会出现复制的情况,这里就是由于模拟的指针的缘故实现的。
其实从总体来说这两个各有利弊,我们在使用的时候需要根据实际的需要来选择相应的类。
Ⅲ Java中HashMap和TreeMap的区别深入理解
HashMap通过hashcode对其内容进行快速查找,而 TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。
HashMap 非线程安全 TreeMap 非线程安全
线程安全
在Java里,线程安全一般体现在两个方面:
1、多个thread对同一个java实例的访问(read和modify)不会相互干扰,它主要体现在关键字synchronized。如ArrayList和Vector,HashMap和Hashtable
(后者每个方法前都有synchronized关键字)。如果你在interator一个List对象时,其它线程remove一个element,问题就出现了。
2、每个线程都有自己的字段,而不会在多个线程之间共享。它主要体现在java.lang.ThreadLocal类,而没有Java关键字支持,如像static、transient那样。
1.AbstractMap抽象类和SortedMap接口
AbstractMap抽象类:(HashMap继承AbstractMap)覆盖了equals()和hashCode()方法以确保两个相等映射返回相同的哈希码。如果两个映射大小相等、包含同样的键且每个键在这两个映射中对应的值都相同,则这两个映射相等。映射的哈希码是映射元素哈希码的总和,其中每个元素是Map.Entry接口的一个实现。因此,不论映射内部顺序如何,两个相等映射会报告相同的哈希码。
SortedMap接口:(TreeMap继承自SortedMap)它用来保持键的有序顺序。SortedMap接口为映像的视图(子集),包括两个端点提供了访问方法。除了排序是作用于映射的键以外,处理SortedMap和处理SortedSet一样。添加到SortedMap实现类的元素必须实现Comparable接口,否则您必须给它的构造函数提供一个Comparator接口的实现。TreeMap类是它的唯一一份实现。
2.两种常规Map实现
HashMap:基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals()[可以重写hashCode()和equals()],为了优化HashMap空间的使用,您可以调优初始容量和负载因子。
(1)HashMap(): 构建一个空的哈希映像
(2)HashMap(Map m): 构建一个哈希映像,并且添加映像m的所有映射
(3)HashMap(int initialCapacity): 构建一个拥有特定容量的空的哈希映像
(4)HashMap(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空的哈希映像
TreeMap:基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。
(1)TreeMap():构建一个空的映像树
(2)TreeMap(Map m): 构建一个映像树,并且添加映像m中所有元素
(3)TreeMap(Comparator c): 构建一个映像树,并且使用特定的比较器对关键字进行排序
(4)TreeMap(SortedMap s): 构建一个映像树,添加映像树s中所有映射,并且使用与有序映像s相同的比较器排序
3.两种常规Map性能
HashMap:适用于在Map中插入、删除和定位元素。
Treemap:适用于按自然顺序或自定义顺序遍历键(key)。
4.总结
HashMap通常比TreeMap快一点(树和哈希表的数据结构使然),建议多使用HashMap,在需要排序的Map时候才用TreeMap。