??xml version="1.0" encoding="utf-8" standalone="yes"?>日本在线丨区,一区二区三区回区在观看免费视频,久久久久久五月天久久久久久久久http://www.aygfsteel.com/himalayas/category/50230.htmlzh-cnThu, 12 Jun 2014 14:35:17 GMTThu, 12 Jun 2014 14:35:17 GMT60install jar to repositoryhttp://www.aygfsteel.com/himalayas/archive/2014/06/12/414667.htmlhimalayashimalayasThu, 12 Jun 2014 09:23:00 GMThttp://www.aygfsteel.com/himalayas/archive/2014/06/12/414667.htmlhttp://www.aygfsteel.com/himalayas/comments/414667.htmlhttp://www.aygfsteel.com/himalayas/archive/2014/06/12/414667.html#Feedback0http://www.aygfsteel.com/himalayas/comments/commentRss/414667.htmlhttp://www.aygfsteel.com/himalayas/services/trackbacks/414667.htmlmvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=6.0.0 -Dpackaging=jar -Dfile=C:\ojdbc6.jar

himalayas 2014-06-12 17:23 发表评论
]]>
HashMap解析http://www.aygfsteel.com/himalayas/archive/2011/01/10/342656.htmlhimalayashimalayasMon, 10 Jan 2011 01:39:00 GMThttp://www.aygfsteel.com/himalayas/archive/2011/01/10/342656.htmlhttp://www.aygfsteel.com/himalayas/comments/342656.htmlhttp://www.aygfsteel.com/himalayas/archive/2011/01/10/342656.html#Feedback0http://www.aygfsteel.com/himalayas/comments/commentRss/342656.htmlhttp://www.aygfsteel.com/himalayas/services/trackbacks/342656.htmlHashMap是基于哈希表的Map接口的实玎ͼ允许null值和null键(HashMap和Hashtable大致一P除了不同步和允许null外)。HashMap不保存映的序Q特别是不保证该序恒久不变?/p>

       HashMap的实现假定hash函数各个元素正分布在各桶之间Q可为基本操作(如get()和set()Q提供稳定的性能QP代集合视图所需的时间与HashMap 实例?#8220;定w”Q桶的数量)及其大小Q键-值映关pLQ的和成比例。所以,如果q代性能很重要,则不要将初始定w讄得太高(或将加蝲因子讄得太低)?Q注Q这D同HashSet很相|其实HashSet是基本HashMap实现的,所以在性能的控制上也一P

       HashMap 的实例有两个参数影响其性能Q初始容量和加蝲因子。容量是哈希表中桶的数量Q初始容量只是哈希表在创建时的容量。加载因子是哈希表在其容量自动增加之前可以达到多满的一U尺度。当哈希表中的条目数出了加载因子与当前定w的乘U时Q通过调用 rehash Ҏ容量翻倍。HashMap的默认初始容量是16Q默认加载因子是0.75Q这P当HashMap里的元素过16*0.75?2Ӟ调用rehashҎQ定w增长一倍?/p>

       通常Q默认加载因?(.75) 在时间和I间成本上寻求一U折街加载因子过高虽然减了I间开销Q但同时也增加了查询成本Q在大多?nbsp;HashMapcȝ操作中,包括 get ?nbsp;put 操作Q都反映了这一点)。在讄初始定w时应该考虑到映中所需的条目数及其加蝲因子Q以便最大限度地降低 rehash 操作ơ数。如果初始容量大于最大条目数除以加蝲因子Q则不会发生 rehash 操作?/p>

       如果很多映射关系要存储在 HashMap 实例中,则相对于按需执行自动?rehash 操作以增大表的容量来_使用_大的初始定w创徏它将使得映射关系能更有效地存储?nbsp;       

       注意Q此实现不是同步的?/strong> 如果多个U程同时讉K此映,而其中至一个线E从l构上修改了该映,则它必须 保持外部同步。(l构上的修改是指d或删除一个或多个映射关系的操作;仅改变与实例已经包含的键兌的g是结构上的修攏V)q一般通过对自然封装该映射的对象进行同步操作来完成。如果不存在q样的对象,则应该?nbsp;Collections.synchronizedMap Ҏ?#8220;包装”该映。最好在创徏时完成这一操作Q以防止Ҏ进行意外的不同步访问,如下所C:

     Map m = Collections.synchronizedMap(new HashMap(...));      

由所有此cȝ“集合视图Ҏ”所q回的P代器都是快速失败的Q在q代器创Z后,如果从结构上Ҏ进行修改,除非通过q代?/p>

自n?remove ?add ҎQ其他Q何时间Q何方式的修改QP代器都将抛出 ConcurrentModificationException 。因此,面对q发

的修改,q代器很快就会完全失败,而不冒在来不确定的旉L发生不确定行为的风险?

注意QP代器的快速失败行Z能得C证,一般来_存在不同步的q发修改Ӟ不可能作ZQ何坚决的保证。快速失败P代器最?/p>

努力抛出 ConcurrentModificationException 。因此,~写依赖于此异常E序的方式是错误的,正确做法是:q代器的快速失败行为应

该仅用于程序错?em style="font-style: italic; ">?/em> HashMap的构造函敎ͼ

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();
    }

可以看出Q当生成HashMap对象Ӟ如果initialCapacity的数值比较大Ӟcapacity 会被赋于{于或大于initialCapacity 的|然后

创徏一个有capacity 个Entry对象的table数组Q所以initialCapacity的数g能太大,否则会生成比较大的数ltableQ占用比较大的应用内

存,造成内存费?/p>

HashMap的默认构造函敎ͼ

public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
        table = new Entry[DEFAULT_INITIAL_CAPACITY];
        init();
    }

默认构造函数里的初始容量ؓ16Q加载因子ؓ0.75Q这样会生成含有16*0.75=12个Entry对象的数ltableQ当HashMap里的元素?/p>

量超q?2个时Q会HashMap的容量翻1倍,生成包含32个Entry对象的数l?/p>

putҎQ?/span>

            public V put(K key, V value) {
        K k = maskNull(key);
        int hash = hash(k);
        int i = indexFor(hash, table.length);

        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            if (e.hash == hash && eq(k, e.key)) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, k, value, i);
        return null;
    }

        K k = maskNull(key);q行是判断key是否为nullQ如果ؓnullQ则q回一个静态的KQObjectQ对象做为键|q就是HashMapZ么允许null键存在的原因?/span>

        int hash = hash(k);
        int i = indexFor(hash, table.length);

        q连l的两步是 HashMap 最牛的地方Q研I完我都汗颜了,其中 hash 是通过 key q个Object?hashcode q行 hashQ然后通过 indexFor 获得在Object table的烦引倹{?/span>

             tableQ?Q不要惊Ӟ其实HashMap也神不到哪里去,它就是用 table 来放的。最牛的是?hash 能正的q回索引。其中的hash法Q我跟JDK的作?Doug 联系q,他徏议我看看《The art of programing vol3》可恨的是,我之前就一直在找,我都找不刎ͼ他这样一提,我就更加急了Q可惜口袋空I啊Q!Q?br /> 不知道大家有没有留意 put 其实是一个有q回的方法,它会把相同键值的 put 覆盖掉ƈq回旧的|如下Ҏd说明?HashMap 的结构,其实是一个表加上在相应位|的Entry的链表:
for (Entry e = table; e != null; e = e.next) {
if (e.hash == hash && eq(k, e.key)) {
Object oldvalue = e.value;
e.value = value; //把新的D予给对应键倹{?br /> e.recordAccess(this); //I方法,留待实现
return oldvalue; //q回相同键值的对应的旧的倹{?br /> }
}
modCount++; //l构性更改的ơ数
addEntry(hash, k, value, i); //d新元素,关键所在!
return null; //没有相同的键D?br /> } 
我们把关键的Ҏ拿出来分析:
void addEntry(int hash, Object key, Object value, int bucketIndex) {
table[bucketIndex] = new Entry(hash, key, value, table[bucketIndex]); 
因ؓ hash 的算法有可能令不同的键值有相同的hash码ƈ有相同的table索引Q如QkeyQ?#8220;33”和keyQObject g的hash都是Q?901334Q那它经qindexfor之后的烦引一定都为iQ这样在new的时候这个Entry的next׃指向q个原本?tableQ再有下一个也如此QŞ成一个链表,和put的@环对定e.next获得旧的倹{到q里QHashMap的结构,大家也十分明白了吧?
if (size++ >= threshold) //q个threshold是能实际容U的?br /> resize(2 * table.length); //出q个定w׃Object table重构 
所谓的重构也不,是Z个两倍大的tableQ我在别的论坛上看到有h说是两倍加1Q把我骗了)Q然后再一个个indexforq去Q注意!Q这是效率Q!如果你能让你的HashMap不需要重构那么多ơ,效率会大大提高!
说到q里也差不多了,get比put单得多,大家Q了解putQget也差不了多少了。对于collections我是认ؓQ它是适合q泛的,当不?全适合Ҏ的,如果大家的程序需要特D的用途,自己写吧Q其实很单。(作者是q样跟我说的Q他q徏议我用LinkedHashMap,我看了源码以后发 玎ͼLinkHashMap其实是l承HashMap的,然后override相应的方法,有兴的同hQ自己looklookQ徏?Object tableQ写相应的算法,ok啦?br /> 举个例子吧,?VectorQlist 啊什么的其实都很单,最多就多了的同步的声明Q其实如果要实现像Vector那种Q插入,删除不多的,可以用一个Object table来实玎ͼ按烦引存取,d{?br /> 如果插入Q删除比较多的,可以Z个Object tableQ然后每个元素用含有nextl构的一个table存,如果要插入到iQ但是i已经有元素,用nextqv来,然后sizeQ+Qƈ在另一个table记录其位|?/span>



himalayas 2011-01-10 09:39 发表评论
]]>
վ֩ģ壺 | | | | ƽ| ƽң| ƺ| | Ϸ| | | | ˱| | | | | ǧ| | | | | | ˳| | ̨| | | | | | | | ٰ| ˮ| | | ½| | | |