今天迭代hashmap时,hashmap并不能按照put的顺序,迭代输出值。用下述方法可以:
HashMap<String,String> hashmap = new LinkedHashMap<String,String>();
方法一:
把HashSet保存在ArrayList里,再用Collections.sort()方法比較
- private void doSort(){
- final HashSet<Integer> va = new HashSet<Integer>();
- va.add(2007111315);
- va.add(2007111314);
- va.add(2007111318);
- va.add(2007111313);
- final List<Integer> list = new ArrayList<Integer>();
- for(final Integer value : va){
- list.add(value);
- }
- Collections.sort(list);
- System.out.println(list);
- }
-
方二法:
把这个HashSet做为构造参数放到TreeSet中就可以排序了
-
- final TreeSet ts = new TreeSet(va);
- ts.comparator();
- System.out.println(ts);
1. HashSet是通过HashMap实现的,TreeSet是通过TreeMap实现的,只不过Set用的只是Map的key
2. Map的key和Set都有一个共同的特性就是集合的唯一性.TreeMap更是多了一个排序的功能.
3. hashCode和equal()是HashMap用的, 因为无需排序所以只需要关注定位和唯一性即可.
a. hashCode是用来计算hash值的,hash值是用来确定hash表索引的.
b. hash表中的一个索引处存放的是一张链表, 所以还要通过equal方法循环比较链上的每一个对象 才可以真正定位到键值对应的Entry.
c. put时,如果hash表中没定位到,就在链表前加一个Entry,如果定位到了,则更换Entry中的value,并返回旧value
4. 由于TreeMap需要排序,所以需要一个Comparator为键值进行大小比较.当然也是用Comparator定位的.
a. Comparator可以在创建TreeMap时指定
b. 如果创建时没有确定,那么就会使用key.com
是的, 这是一个太多太多人遇到过, 讨论过, 解释过的问题.
为了加深自己的记忆, 还是决定写一篇来记录下他.
首先想说的是:
Vector是在Collections API之前就已经产生了的, 而ArrayList是在JDK1.2的时候才作为Collection framework的一部分引入的. 它们都是在内部用一个Obejct[]来存储元素的.
ok, 现在来说他们的差别:
1. 线程安全
Vector是同步的, 而ArrayList不是.
因为Vector是同步的, 所以它是线程安全的.
同样, 因为Vecotr是同步的, 所以他需要额外的开销来维持同步锁, 所以它要比ArrayList要慢.(理论上来说)
当然, 如果你对ArrayList有偏好, 你也可以用Collection.synchronizedList(List)来得到一个线程安全的List.
2. 容量增长
Vector允许用户设置capacityIncrement这样在每次需要扩充数组的size的时候, Vector会尝试按照预先设置的capacityIncrement作为增量来设置, 而ArrayList则会把数组的大小扩大一倍.
比如现在同样一个长度为10的Vector和ArrayList, 我们把Vector的capacityIncrement设为1
那么我们在插入第11个对象的时候, Vector会将长度变成11, 然后分配空间, 然后将对象添加进去, 而ArrayList则会分配20个对象的空间, 然后将对象添加进去.
如果capacityIncrement设为0或者负值, Vector就会做和ArrayList一样, 每次都将数组大小扩大一倍.
3. 性能比较
刚刚在上面已经说过了, 由于Vector是同步的, 而ArrayList不是, 所以Vector的性能要比ArrayList要稍第一点, 用性能换安全嘛.
不过, 据Jack Shirazi在OnJava上的一篇文章来看, 似乎这并不是什么问题, 他认为对于现在的JVM来说, 这两个类在同步这个问题上的性能差异, 甚至还不如每次跑测试的时候环境变化引起的差异大.
Consequently Vector is thread-safe, and ArrayList isn't. This makes ArrayList faster than Vector. For some of the latest JVMs the difference in speed between the two classes is negligible: strictly speaking, for these JVMs the difference in speed between the two classes is less than the variation in times obtained from tests comparing the performance of these classes. ---- The Performance of Java's Lists
这样看来, 性能上的差别应该不大.
So, as a conclusion.
结论和网上大多数人得到的结论一样:
在一般情况下, 还是鼓励用ArrayList的, 如果你有同步控制的需要, 那就用Vector吧, 也懒得用Collection.synchronizedList(List)再去转一次了, 除非非这样不可.. 不然还是顺应潮流, 毕竟, 代码是写给人看的. 在无伤大雅的情况下, 按照common的法则来写, 无疑会让看代码的人更快理解. :)
1、 继承和实现区别
Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现。
2、 线程安全不同
HashTable的方法是同步的,HashMap是未同步,所以在多线程场合要手动同步HashMap。
3、 对null的处理不同
HashTable不允许null值(key和value都不可以),HashMap允许null值(key和value都可以)。即HashTable 不允许null值其实在编译期不会有任何的不一样,会照样执行,只是在运行期的时候Hashtable中设置的话回出现空指针异常。HashMap允许 null值是指可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。
4、 方法不同
HashTable有一个contains(Object value),功能和containsValue(Object value)功能一样。
5、HashTable使用Enumeration,HashMap使用Iterator。
6、HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
7、哈希值的使用不同,HashTable直接使用对象的hashCode,代码是这样的:
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
而HashMap重新计算hash值,而且用与代替求模:
int hash = hash(k);
int i = indexFor(hash, table.length);
static int hash(Object x) {
int h = x.hashCode();
h += ~(h << 9);
h ^= (h >>> 14);
h += (h << 4);
h ^= (h >>> 10);
return h;
}
static int indexFor(int h, int length) {
return h & (length-1);
}
区别 |
Hashtable |
Hashmap |
继承、实现 |
Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable,Serializable |
HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable,Serializable
|
线程同步 |
已经同步过的可以安全使用 |
未同步的,可以使用Colletcions进行同步Map Collections.synchronizedMap(Map m) |
对null的处理
|
Hashtable table = new Hashtable(); table.put(null, "Null"); table.put("Null", null); table.contains(null); table.containsKey(null); table.containsValue(null); 后面的5句话在编译的时候不会有异常,可在运行的时候会报空指针异常具体原因可以查看源代码 public synchronized V put(K key, V value) { // Make sure the value is not null if (value == null) { throw new NullPointerException(); } |
HashMap map = new HashMap(); map.put(null, "Null"); map.put("Null", null); map.containsKey(null); map.containsValue(null); 以上这5条语句无论在编译期,还是在运行期都是没有错误的. 在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。 |
增长率 |
protected void rehash() { int oldCapacity = table.length; Entry[] oldMap = table; int newCapacity = oldCapacity * 2 + 1; Entry[] newMap = new Entry[newCapacity]; modCount++; threshold = (int)(newCapacity * loadFactor); table = newMap; for (int i = oldCapacity ; i-- > 0 ;) { for (Entry<K,V> old = oldMap[i] ; old != null ; ) { Entry<K,V> e = old; old = old.next; int index = (e.hash & 0x7FFFFFFF) % newCapacity; e.next = newMap[index]; newMap[index] = e; } } }
|
void addEntry(int hash, K key, V value, int bucketIndex) { Entry<K,V> e = table[bucketIndex]; table[bucketIndex] = new Entry<K,V>(hash, key, value, e); if (size++ >= threshold) resize(2 * table.length); }
|
哈希值的使用 |
HashTable直接使用对象的hashCode,代码是这样的: public synchronized booleancontainsKey(Object key) { Entry tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { return true; } } return false; } |
HashMap重新计算hash值,而且用与代替求模 public boolean containsKey(Object key) { Object k = maskNull(key); int hash = hash(k.hashCode()); int i = indexFor(hash, table.length); Entry e = table[i]; while (e != null) { if (e.hash == hash && eq(k, e.key)) return true; e = e.next; } return false; }
|
相关推荐
自己写的例子,关于HashSet遍历和HashMap遍历的. 感谢大家参考
treemap treeset hashset hashmap 简要介绍
主要介绍了Java中HashSet和HashMap的区别_动力节点Java学院整理,需要的朋友可以参考下
HashMap底层实现原理HashMap与HashTable区别HashMap与HashSet区别。HashMap、HashTable和HashSet是Java中常用的数据结构,它们的底层实现原理以及区别如下:HashMap底层实现原理: HashMap基于哈希表(HashTable)...
什么是HashSet? HashSet实现了Set接口,它不允许集合中有重复的值,当我们提到HashSet时,第一件事情就是在将对象存储在HashSet之前,要先确保对象重写equals()和hashCode()方法,这样才能比较对象的值是否相等,以...
HashTable不支持空键值对! 而HashMap支持空键值对!
编写一个查询类,输入学生学号,若该生在数据文件(test.txt)中存在,在JTextArea中显示该生信息 若该生在数据文件(test.txt)中不存在,显示”查无此人”,可反复查找.在输出中,能显示该生的总成绩和平均成绩,将显示结果...
之所以把HashSet和HashMap放在一起讲解,是因为二者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也是说HashSet里面有一个HashMap(适配器模式)。因此本文将重点分析HashMap。 HashMap实现了Map...
HashSet的实现原理 ,HashSet与HashMap的区别 以及 HashSet的底层实现方式
HashSet HashMap LinkedList 遍历方法 传统遍历方法 for(int i=0;i<list.size();i++) { String str = list.get(i); ... } 内置迭代器 for (String str : list) { ... } 显式迭代器 Iterator it = list....
数据结构 简单的数据结构,包括HashSet,HashMap,Heap,Red-Black Tree等。
主要介绍了从源码的角度浅析HashMap、TreeMap元素的存储和获取元素的逻辑;从Map与Set之间的关系浅析常用的Set中元素的存储和判断是否重复的逻辑,需要的朋友可以参考下
通过 HashMap、HashSet 的源代码分析其 Hash 存储机制1
对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSet 的源代码,可以看到如下代码:
本文主要介绍HashMap 和 HashSet的区别,这里整理了详细的资料来说名两者的区别,并说明如何使用该方法,有需要的小伙伴可以参考下
本文档对javaAPI中的set,map...leetcode第三题,hashset与hashmap 关于寻找最长的不重复的子字符串的一个简单的问题可以很好的使用到hashset与hashmap两个类。首先对hashset与hashmap两个类进行一个简单的解释与说明。
HashMap和HashSet是Java Collection Framework的两个重要成员,其中HashMap是Map接口的常用实现类,HashSet是Set接口的常用实现类。虽然HashMap和HashSet实现的接口规范不同,但它们底层的Hash存储机制完全一样,...
- HashMap 和 HashSet 的区别 - HashMap 底层结构 - AbstractMap 类 - Map 接口 - 重要内部类和接口 - Node 接口 - KeySet 内部类 - Values 内部类 - EntrySet 内部类 - HashMap 1.7 的底层结构 - ...
HashSet 是 Java 中的一个集合类,它实现了 Set 接口并提供了基于哈希表的无序、不重复元素的集合。具体来说,它是通过哈希表(实际上是一个 HashMap 实例)来存储元素的。 以下是 HashSet 的一些主要特点: 无序...