Difference between HashMap, LinkedHashMap and TreeMap
在Java中EDCOX1与0、EDCX1、1和EDCX1 2的区别是什么?我看不出输出有什么不同,因为这三个都有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | Map m1 = new HashMap(); m1.put("map","HashMap"); m1.put("schildt","java2"); m1.put("mathew","Hyden"); m1.put("schildt","java2s"); print(m1.keySet()); print(m1.values()); SortedMap sm = new TreeMap(); sm.put("map","TreeMap"); sm.put("schildt","java2"); sm.put("mathew","Hyden"); sm.put("schildt","java2s"); print(sm.keySet()); print(sm.values()); LinkedHashMap lm = new LinkedHashMap(); lm.put("map","LinkedHashMap"); lm.put("schildt","java2"); lm.put("mathew","Hyden"); lm.put("schildt","java2s"); print(lm.keySet()); print(lm.values()); |
我喜欢视觉展示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ╔══════════════╦═════════════════════╦═══════════════════╦═════════════════════╗ ║ Property ║ HashMap ║ TreeMap ║ LinkedHashMap ║ ╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣ ║ Iteration ║ no guarantee order ║ sorted according ║ ║ ║ Order ║ will remain constant║ to the natural ║ insertion-order ║ ║ ║ over time ║ ordering ║ ║ ╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣ ║ Get/put ║ ║ ║ ║ ║ remove ║ O(1) ║ O(log(n)) ║ O(1) ║ ║ containsKey ║ ║ ║ ║ ╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣ ║ ║ ║ NavigableMap ║ ║ ║ Interfaces ║ Map ║ Map ║ Map ║ ║ ║ ║ SortedMap ║ ║ ╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣ ║ ║ ║ ║ ║ ║ Null ║ allowed ║ only values ║ allowed ║ ║ values/keys ║ ║ ║ ║ ╠══════════════╬═════════════════════╩═══════════════════╩═════════════════════╣ ║ ║ Fail-fast behavior of an iterator cannot be guaranteed ║ ║ Fail-fast ║ impossible to make any hard guarantees in the presence of ║ ║ behavior ║ unsynchronized concurrent modification ║ ╠══════════════╬═════════════════════╦═══════════════════╦═════════════════════╣ ║ ║ ║ ║ ║ ║Implementation║ buckets ║ Red-Black Tree ║ double-linked ║ ║ ║ ║ ║ buckets ║ ╠══════════════╬═════════════════════╩═══════════════════╩═════════════════════╣ ║ Is ║ ║ ║ synchronized ║ implementation is not synchronized ║ ╚══════════════╩═══════════════════════════════════════════════════════════════╝ |
这三个类都实现了
HashMap 对迭代顺序绝对没有保证。当添加新元素时,它甚至可以(也将)完全改变。TreeMap 将根据密钥的"自然排序"根据它们的compareTo() 方法(或外部提供的Comparator 方法)进行迭代。此外,它还实现了SortedMap 接口,其中包含依赖于此排序顺序的方法。LinkedHashMap 将按条目放入地图的顺序迭代。
"hashtable"是基于哈希的映射的通用名称。在Java API的上下文中,在集合框架存在之前,从1.1 Java时代开始,EDCOX1 9是一个过时的类。它不应该再被使用了,因为它的API中充斥着重复功能的过时方法,并且它的方法是同步的(这会降低性能,通常是无用的)。使用ConcurrentHashMap而不是HashTable。
这三个都表示从唯一键到值的映射,因此实现了映射接口。
hashmap是基于键散列的映射。它支持O(1)获取/输出操作。密钥必须具有一致的
linkedhashmap与hashmap非常相似,但它增加了对添加(或访问)项的顺序的认识,因此迭代顺序与插入顺序(或访问顺序,取决于构造参数)相同。
treemap是基于树的映射。它的输入/获取操作需要O(log n)时间。它要求项目具有某种比较机制,可以使用比较器或比较器。迭代顺序由这个机制决定。
在下图中查看每个类在类层次结构中的位置(较大的一个)。treemap执行
哈希图
- 它有对值(键、值)
- 无重复键值
- 无序未排序
- 它允许一个空键和多个空值
散列表
- 与哈希图相同
- 它不允许空键和空值
链接地图
- 它是映射实现的有序版本
- 基于链表和散列数据结构
树图
- 订购和分类版本
- 基于哈希数据结构
只是从我自己的地图经验中得到更多的信息,关于我何时使用每个地图:
- hashmap-在寻找最佳性能(快速)实现时最有用。
- treemap(sortedmap interface)——当我考虑到能够按照我定义的特定顺序对键进行排序或迭代时最有用。
- Linkedhashmap-结合了保证从TreeMap订购的优点,而不增加维护TreeMap的成本。(几乎和哈希图一样快)。尤其是,linkedhashmap还提供了通过重写
removeEldestEntry() 方法来创建缓存对象的一个很好的起点。这允许您创建一个缓存对象,该对象可以使用您定义的某些条件使数据过期。
所有三个类
哈希图
它只包含唯一的元素。
它可以有一个空键和多个空值。
它没有维持秩序。
链接地图
它与hashmap相同,而维护插入顺序。//见下面的减速等级
树图
它与
哈希表
它是一个传统类。
HashMap makes absolutely not guarantees about the iteration order. It
can (and will) even change completely when new elements are added.
TreeMap will iterate according to the"natural ordering" of the keys
according to their compareTo() method (or an externally supplied
Comparator). Additionally, it implements the SortedMap interface,
which contains methods that depend on this sort order. LinkedHashMap
will iterate in the order in which the entries were put into the map
看看性能如何变化……
树映射,是排序映射的一种实现。由于自然排序,Put、Get和ContainsKey操作的复杂性为O(log n)。
@amit:
1 2 3 | public class TreeMap<K,V> extends AbstractMap<K,V> implements SortedMap<K,V>, Cloneable, Serializable |
坚果壳
以下是hashmap和treemap之间的主要区别
hashmap不维护任何顺序。换言之,hashmap不保证首先插入的元素会被打印出来,就像treeset一样,treemap元素也会按照元素的自然顺序排序。
内部hashmap实现使用散列,treemap内部使用红黑树实现。
哈希映射可以存储一个空键和多个空值。TreeMap不能包含空键,但可以包含多个空值。
hashmap对get和put等基本操作(即o(1))采用恒定的时间性能,根据Oracle文档,treemap为get和put方法提供了保证的日志(n)时间成本。
hashmap比treemap快得多,因为对于大多数操作,hashmap的性能时间与日志时间treemap相比是恒定的。
hashmap使用equals()方法进行比较,treemap使用compareto()方法维护顺序。
hashmap实现映射接口,treemap实现navigablemap接口。
这些是同一接口的不同实现。每个实现都有一些优点和缺点(快速插入、缓慢搜索),反之亦然。
有关详细信息,请查看treemap、hashmap、linkedhashmap的javadoc。
HashMap:
- 订单未维护
- 比Linkedhashmap快
- 用于存储对象堆
LinkedHashMap:
- 将维护LinkedHashMap插入顺序
- 比hashmap慢,比treemap快
- 如果要保持插入顺序,请使用此选项。
TreeMap:
- treemap是基于树的映射
- Treemap将遵循键的自然顺序
- 比hashmap和linkedhashmap慢
- 需要保持自然(默认)排序时使用treemap
哈希映射不保留插入顺序。例子。散列图如果插入的键为
1 2 3 4 5 | 1 3 5 9 4 6 7 15 3 10 |
它可以存储为
1 2 3 4 5 | 4 6 5 9 3 10 1 3 7 15 |
链接的hashmap保留插入顺序。
例子。如果你在插入钥匙
1 2 3 4 5 | 1 3 5 9 4 6 7 15 3 10 |
它将存储为
1 2 3 4 5 | 1 3 5 9 4 6 7 15 3 10 |
和我们插入的一样。
树图按键的递增顺序存储山谷。例子。如果你在插入钥匙
1 2 3 4 5 | 1 3 5 9 4 6 7 15 3 10 |
它将存储为
1 2 3 4 5 | 1 3 3 10 4 6 5 9 7 15 |
它们都提供了一个键->值映射和一种迭代键的方法。最重要的区别在于这些类是时间保证和键的顺序。
假设您将空的treemap、hashmap和linkedhashmap传递到以下函数:
1 2 3 4 5 6 7 8 9 |
每个的输出结果如下所示。
对于hashmap,在我自己的测试中,输出是0,1,-1,但它可以是任何顺序。没有保证排序。Treemap,输出是,-1,0,1LinkedList,输出为,1,-1,0_
哈希图不能包含一个空键。
hashmap不维护任何顺序。
树图
treemap不能包含任何空键。
Treemap保持升序。
链接地图
linkedhashmap可以用来维护插入顺序,在这个顺序上键被插入到映射中,或者也可以用来维护访问顺序,在这个顺序上键被访问。
实例:
1)hashmap=new hashmap();
1 2 3 4 5 6 7 8 |
2)treemap map=new treemap();
1 2 3 4 5 6 7 8 |
3)linkedhashmap=new linkedhashmap();
1 2 3 4 5 6 7 8 |