- 浏览: 625182 次
- 性别:
- 来自: 西安
文章分类
最新评论
-
d1438138:
[img][/img]
google api 的一些神奇使用 -
waykingeye:
[i][b][u]引用[list]
[*][img][url] ...
No result defined for action and result input -
tss0823:
...
No result defined for action and result input -
yahier:
有什么办法能够捕捉,然后给出自定义的提示呢
No result defined for action and result input -
chen_lian:
恩恩 按照上面的代码测试一下觉得很对
java创建目录
提起map,这个java中collection家族中的典范,特别是hashmap更是大家耳熟能详的工具类,下面就细细的看看
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { /** * The default initial capacity - MUST be a power of two. */ static final int DEFAULT_INITIAL_CAPACITY = 16; /** * The maximum capacity, used if a higher value is implicitly specified * by either of the constructors with arguments. * MUST be a power of two <= 1<<30. */ static final int MAXIMUM_CAPACITY = 1 << 30; /** * The load factor used when none specified in constructor. */ static final float DEFAULT_LOAD_FACTOR = 0.75f; /** * The table, resized as necessary. Length MUST Always be a power of two. */ transient Entry[] table; /** * The number of key-value mappings contained in this map. */ transient int size;
/** * The next size value at which to resize (capacity * load factor). * @serial */ int threshold;
/** * The load factor for the hash table. * * @serial */ final float loadFactor;
/** * The number of times this HashMap has been structurally modified * Structural modifications are those that change the number of mappings in * the HashMap or otherwise modify its internal structure (e.g., * rehash). This field is used to make iterators on Collection-views of * the HashMap fail-fast. (See ConcurrentModificationException). */ transient volatile int modCount;
这是Hashmap中的实例变量(jdk1.6),其中大家可以看到hashmap的实质其实是一个transient Entry[] table数组,另外像DEFAULT_INITIAL_CAPACITY(默认容量),MAXIMUM_CAPACITY最大容量(2^30),DEFAULT_LOAD_FACTOR默认装载因子(0.75),这些都是staic final的,用来当做默认配置和检查边界的,另外可以设置的3个也是我们一般传进去的参数,size(这个是记录map内存了多少对数据的),threshold,loadFactor,分别是边界值,加载因子,关系就是threshold=a*loadFactor,意思就是你的table初始化为a大小,当你不断添加内容到了threshold大小时,table就要自动加倍了。
public HashMap(int initialCapacity, float loadFactor) { if (initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity); if (initialCapacity > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; if (loadFactor <= 0 || Float.isNaN(loadFactor)) throw new IllegalArgumentException("Illegal load factor: " + loadFactor); // Find a power of 2 >= initialCapacity int capacity = 1; while (capacity < initialCapacity) capacity <<= 1; this.loadFactor = loadFactor; threshold = (int)(capacity * loadFactor); table = new Entry[capacity]; init(); }
这个就是我们常用的构造函数,基本上就是对初始容量大小,loadFactor的检查,以及最关键的table = new Entry[capacity];,其中capacity并不是我们制定多少,他就是多少,实际上他选择了刚好小于输入initialCapacity的2的倍数作为大小,
public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
这就是著名的put函数了,注意这里可以明显看到hashmap不是同步的,以及他可以接受空值为键,此外大家也可以明显看到一个良好的key的hashcode()还是很必要的,如果设置了一个垃圾的hashcode()函数,那么
static int hash(int h) { // This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 at default load factor). h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); }
即便HashMap的hash函数也无能为力了,当得到处理过的32位hash码后,还要继续处理得到table[]的index
static int indexFor(int h, int length) { return h & (length-1); }
很简单的一个函数,利用table的长度很好的截出了适当的大小,然后就是利用index在table中开始找key了,很明显这个就是直到找到为空或者找到"相同的"key,然后覆盖,如果没有调用addEntry
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
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); }
这里很明显,就看到了每当新加一个Entry时,size++,并且如果size>threshold(就是前面两者相乘的结果),则table长度翻倍。
get基本上类似,就不细讲了,下来看看hashmap中很实用的keySet(),
public Set<K> keySet() { Set<K> ks = keySet; return (ks != null ? ks : (keySet = new KeySet())); } private final class KeySet extends AbstractSet<K> { public Iterator<K> iterator() { return newKeyIterator(); } public int size() { return size; } public boolean contains(Object o) { return containsKey(o); } public boolean remove(Object o) { return HashMap.this.removeEntryForKey(o) != null; } public void clear() { HashMap.this.clear(); } }
明显keyset()返回的是一个内部类实现了AbstractSet,而这个内部类中实际上的每一个set操作,都直接影响着Haspmap中的数据。
在这个内部类中我们还能看到一个非常多见的方法public Iterator<K> iterator(),这个方法伴随在collection的每一个角落
private abstract class HashIterator<E> implements Iterator<E> { Entry<K,V> next; // next entry to return int expectedModCount; // For fast-fail int index; // current slot Entry<K,V> current; // current entry HashIterator() { expectedModCount = modCount; if (size > 0) { // advance to first entry Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } } public final boolean hasNext() { return next != null; } final Entry<K,V> nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); Entry<K,V> e = next; if (e == null) throw new NoSuchElementException(); if ((next = e.next) == null) { Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } current = e; return e; } public void remove() { if (current == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); Object k = current.key; current = null; HashMap.this.removeEntryForKey(k); expectedModCount = modCount; } }
这同样是Hashmap中的一个内部类,而且这还是一个实现Iterator的抽象类,在hashmap中有3个用来对keyset,value,和entry返回iterator的内部类均是继承HashIterator,而且很明显的可以看到对iterator的任何改变都会带来Hashmap的改变,特别要注意的是 expectedModCount = modCount;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
这里实际上是保证了在iterator遍历Hashmap过程中对Hashmap的改变(增加和删除均会带来modCount的增加,可以看前面的put函数),均会导致iterator扔出异常,但仔细看put函数,我们又会发现如果只是value的更替,而不是新加,modCount 不会发生变化。
Iterator<K> newKeyIterator() { return new KeyIterator(); } Iterator<V> newValueIterator() { return new ValueIterator(); } Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }
因为HashIterator实现的很好了,故每个自己的iterator就实现的很简单了
private final class KeyIterator extends HashIterator<K> { public K next() { return nextEntry().getKey(); } }
好了Hashmap就大概讲这么多,明天再从Hashmap铺开比较更多的map
发表评论
-
struts2远程执行漏洞学习(四)
2013-05-23 00:12 22390x01 最近又有了一个新的struts2漏洞,http:/ ... -
纯转一篇关于方法句柄的,对理解很多java poc帮助很大
2013-04-19 15:16 4261http://book.2cto.com/20130 ... -
CVE-2013-1493 学习
2013-03-25 16:06 28630x01 这个又是一个java CVE,效果前几个一样, ... -
myeclipse崩溃多处理的一个小窍门
2013-01-15 20:23 31140x01 如果大家用了myeclipse10以上版本,忽然间 ... -
CVE-2013-0422 分析2
2013-01-11 23:47 33190x01 http://wcf1987.iteye.c ... -
CVE-2013-0422 学习
2013-01-11 16:26 40660x01 这个是这两天爆出来的,我构建了一个本地测试代码,主 ... -
CVE 2012 0507 分析
2012-12-17 16:00 35220x01 https://github.com/wche ... -
<找工作 十一>生产者消费者 组赛队列
2012-09-25 17:39 1483用阻塞队列实现 import java.util.co ... -
<找工作 十>生产者 消费者模型
2012-09-25 16:54 1110今天被问了个这个问 ... -
<找工作 九> 字符串全排列问题
2012-09-23 22:01 1353public class StringTest { ... -
<找工作 七>leetcode Add Two Numbers
2012-09-13 22:24 3101Add Two Numbers 链表相加 p ... -
<找工作 六>leetcode Median of Two Sorted Arrays
2012-09-13 21:25 3209http://www.leetcode.com/onlinej ... -
java+jfreechart 做股票日线数据查看系统
2012-07-02 19:56 2323如标题所说,有需要jfreechart做股票日线之类的东西的人 ... -
struts2远程执行漏洞学习(三)
2012-02-24 16:27 5093这个是终结部分了。 除了#_memb ... -
struts2远程执行漏洞学习(二)
2012-02-24 13:38 2862http://commons.apache.org/ogn ... -
struts2远程执行漏洞学习(一)
2012-02-23 16:46 2256首先,这个漏洞已经是比较早的一个了,大概影响范围是 ... -
String和input Stream的转换问题
2011-07-27 17:05 3527问题的背景是需求要生 ... -
关于apache解压zip和sleep程序程序退出问题
2011-03-02 16:26 1456前两天写了 http://wcf1987.iteye.com ... -
zip与unzip
2011-01-24 22:39 7531大家在用java做zip压缩解压缩时,java提供了原生的zi ... -
java调用外部程序控制(三)进阶
2011-01-23 16:25 1544接上次的内容,我们在用java调用外部exe,有时会发生exe ...
相关推荐
《java编程思想》,Map结合HashMap获取键相关联的值
比较Java原生的 3种Map的效率。 1. TreeMap 2. HashMap 3. ConcurrentSkipListMap 本测试查找方法使用Map的get方法,循环、离散获取。对于ConcurrentSkipListMap,获得顺序片段,可用subMap()方法,提取50w的子序列...
用数据结构的思想实现java中的类hashmap
可以通过2种方法遍历HashMap <br>Map map = new HashMap(); <br>for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) { <br> Map.Entry entry = (Map.Entry) iter.next(); <br> Object ...
马士兵老师HashMap学习笔记
Map,HashMap,TreeMap的使用 很详细额,值得看看
1、遍历Map.entrySet():它的每一个元素都是Map.Entry对象,这个对象中, 放着的就是Map中的某一对key-value; 2、遍历Map.keySet():它是Map中key值的集合,我们可以通过遍历这个集合来 读取Map中的元素; 3、...
要求:从键盘输入5本书的名称、单价、购买数量,将这些信息存入一个HashMap,然后将该HashMap作为参数调用方法getSum(HashMap books),该方法用于计算书的总价并返回。【说明:键盘输入可以使用Scanner类】
JNI处理hashmap,string等对象的操作,别处绝对没有的
HashMap存放.doc
hashMap基本工作原理,图解分析,基础Map集合
从一个公司的项目中提取的一个基于共享内存的hashMap,vector,list等的相关实现,应用与游戏服务器的数据保存与访问
List、ArrayList、Vector及map、HashTable、HashMap分别的区别
结合Java的HashMap中的一些优点,改进了C++ 的hash_map。 详细说明见我的博客:http://blog.csdn.net/mdj67887500/article/details/6907702
C语言实现hashMap,包含创建hashMap、插入hashMap、查找hashMap、删除hashMap,已经若干经典的hash函数。文章链接:https://blog.csdn.net/sxf1061700625/article/details/109594495
使用jQuery开发HashMap,包含一些基本的功能。
hashmap实例 hashmap实例hashmap实例hashmap实例
HashMap介绍和使用
一个用于js里面 用javascript实现的HashMap类
一个delphi写的hashmap源代码, 包括TIntegerHashList, TStringHashList, TObjectHashList. 十万条记录查找只用 400毫秒.