<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理
        update1:添加了remove,removeAll()方法以及getSize()方法
        update2:添加了keySet()方法用于迭代  
        update3:經(jīng)過測試,StTable類在存儲Integer類型key時,put的速度比HashMap快了接近3倍,而remove、get卻比HashMap慢;而在存儲String類型的key時,put比Hashmap慢,但是get、remove卻快不少。

        讀ruby hacking guide,其中專門辟了一個章節(jié)介紹了st.c中的st_table,這個數(shù)據(jù)結(jié)構(gòu)也就是類似java中的HashMap,基本原理是利用數(shù)組存儲,數(shù)組的每一個元素是一個單向鏈表,鏈表中再存儲具體的元素,如下圖所示的結(jié)構(gòu)

       ruby中利用這個結(jié)構(gòu)來存儲對象變量、類方法、常量、全局變量等信息,因為在c ruby中,方法、變量都是用一個整型作為鍵值來存儲在st_table中,因此這個數(shù)據(jù)結(jié)構(gòu)對于以整性為鍵值的map類型來說速度非常不錯(我沒有測試內(nèi)存的占用情況)。
    源碼如下:
    //接口,用于定義hash函數(shù)
    //HashFunction.java
    public interface HashFunction<T> {
       
    public int hash(T key);
    }

    鏈表元素類:
    public class StTableEntry<T, V> {
        
    protected int hash; //hash值

        
    protected T key;   //

        
    protected V value; //存儲值

        
    protected StTableEntry<T, V> next; //下一節(jié)點(diǎn)

        
    public StTableEntry() {

        }

        
    public StTableEntry(int hash, T key, V value, StTableEntry<T, V> next) {
            
    super();
            
    this.hash = hash;
            
    this.key = key;
            
    this.value = value;
            
    this.next = next;
        }

        
    public int getHash() {
            
    return hash;
        }

        
    public void setHash(int hash) {
            
    this.hash = hash;
        }

        
    public T getKey() {
            
    return key;
        }

        
    public void setKey(T key) {
            
    this.key = key;
        }

        
    public StTableEntry<T, V> getNext() {
            
    return next;
        }

        
    public void setNext(StTableEntry<T, V> next) {
            
    this.next = next;
        }

        
    public V getValue() {
            
    return value;
        }

        
    public void setValue(V value) {
            
    this.value = value;
        }

    }

    完整的StTable實(shí)現(xiàn),沒有實(shí)現(xiàn)remove,(update:添加了remove,removeAll()方法以及getSize()方法):
    public final class StTable<T, V> {
        
    private HashFunction<T> hashFunction;

        
    private int num_bins;

        
    int num_entries;

        StTableEntry
    <T, V>[] bins;

        
    public static int DEFAULT_SIZE = 11;

        
    private static int DEFAULT_MAX_DENSITY = 5;

        
    private static int DEFAULT_MIN_SIZE = 8;

        
    private static long primes[] = { 8 + 316 + 332 + 564 + 3128 + 3,
                
    256 + 27512 + 91024 + 92048 + 54096 + 38192 + 27,
                
    16384 + 4332768 + 365536 + 45131072 + 29262144 + 3,
                
    524288 + 211048576 + 72097152 + 174194304 + 158388608 + 9,
                
    16777216 + 4333554432 + 3567108864 + 15134217728 + 29,
                
    268435456 + 3536870912 + 111073741824 + 850 };

        
    public StTable(HashFunction<T> hashFunction) {
            
    this.hashFunction = hashFunction;
            
    this.num_bins = DEFAULT_SIZE;
            
    this.num_entries = 0;
            
    this.bins = new StTableEntry[this.num_bins];
        }

        
    public StTable(HashFunction<T> hashFunction, int size) {
            
    this.hashFunction = hashFunction;
            
    if (size == 0)
                
    throw new IllegalArgumentException(
                        
    "The size could not less than zero:" + size);
            
    this.num_bins = size;
            
    this.num_entries = 0;
            
    this.bins = new StTableEntry[this.num_bins];
        }

        
    private long newSize(int size) {

            
    for (int i = 0, newsize = DEFAULT_MIN_SIZE; i < primes.length; i++, newsize <<= 1) {
                
    if (newsize > size)
                    
    return primes[i];
            }
            
    /* Ran out of polynomials */
            
    return -1/* should raise exception */
        }

        
    public V get(T key) {
            
    int hash_val = doHash(key);
            StTableEntry
    <T, V> entry = findEntry(hash_val, key);
            
    if (entry == null)
                
    return null;
            
    else
                
    return entry.getValue();
        }

        
    public V put(T key, V value) {
            
    int hash_val = doHash(key);
            StTableEntry
    <T, V> entry = findEntry(hash_val, key);
            
    if (entry == null) {
                
    // 未有鍵值,直接添加
                addDirect(key, value);
                
    return value;
            } 
    else {
                V v 
    = entry.value;
                entry.value 
    = value;
                
    return v;
            }
        }

        
    public V remove(T key) {
            
    int hash_val = doHash(key);
            
    int bin_pos = hash_val % this.num_bins;
            StTableEntry
    <T, V> entry = this.bins[bin_pos];
            
    // 記錄前一節(jié)點(diǎn),考慮修改采用雙向鏈表也可
            StTableEntry<T, V> prev = null;
            
    if (entryNotEqual(entry, key, hash_val)) {
                prev 
    = entry;
                entry 
    = entry.next;
                
    while (entryNotEqual(entry, key, hash_val)) {
                    prev 
    = entry;
                    entry 
    = entry.next;
                }
            }
            
    if (entry == null)
                
    return null;
            
    else {
                
    if (prev != null)
                    prev.next 
    = entry.next; // 前一節(jié)點(diǎn)的next連接到下一節(jié)點(diǎn)
                else
                    
    this.bins[bin_pos] = entry.next; // entry恰好是第一個節(jié)點(diǎn),將數(shù)組元素設(shè)置為next
                V v = entry.value;
               
    entry = null// gc友好
                return v;
            }
           
    this.num_entries=0;
        }

        
    public void removeAll() {
            
    for (int i = 0; i < this.bins.length; i++) {
                StTableEntry
    <T, V> entry = this.bins[i];
                
    this.bins[i] = null;
                StTableEntry
    <T, V> temp = entry;
                
    if (entry == null)
                    
    continue;
                
    while (entry != null) {
                    entry 
    = null;
                    
    this.num_entries--;
                    entry 
    = temp.next;
                    temp 
    = entry;
                }
                temp 
    = null;
                entry 
    = null;
            }
        }

        
    public int getSize() {
            
    return this.num_entries;
        }
       
       
    public Set<T> keySet() {
            Set<T> keys = new HashSet<T>(this.num_entries);
            for (int i = 0; i < this.bins.length; i++) {
                StTableEntry<T, V> entry = this.bins[i];
                if (entry == null)
                    continue;
                while (entry != null) {
                    keys.add(entry.key);
                    entry = entry.next;
                }

            }
            return keys;
        }
        
    // hash函數(shù),調(diào)用hashFunction的hash方法
        private int doHash(T key) {
            
    if (hashFunction.hash(key) < 0)
                
    throw new IllegalArgumentException(
                        
    "hash value could not less than zero:"
                                
    + hashFunction.hash(key));
            
    return hashFunction.hash(key);
        }

        
    // 過于擁擠,重新分布
        private void reHash() {
            
    int new_size = (int) newSize(this.num_bins);
            StTableEntry
    <T, V>[] new_bins = (StTableEntry<T, V>[]) new StTableEntry[new_size];
            
    for (int i = 0; i < this.num_bins; i++) {
                StTableEntry
    <T, V> entry = this.bins[i];
                
    while (entry != null) {
                    StTableEntry
    <T, V> next = entry.next;
                    
    int hash_val = entry.hash % new_size;
                    entry.next 
    = new_bins[hash_val];
                    new_bins[hash_val] 
    = entry;
                    entry 
    = next;
                }
            }
            
    this.bins = null;// gc友好
            this.num_bins = new_size;
            
    this.bins = new_bins;

        }

        
    private void addDirect(T key, V value) {
            
    int hash_val = doHash(key);
            
    int bin_pos = hash_val % this.num_bins;
            
    if ((this.num_entries / this.num_bins) > DEFAULT_MAX_DENSITY) {
                reHash();
                bin_pos 
    = hash_val % this.num_bins;
            }
            StTableEntry
    <T, V> entry = new StTableEntry<T, V>();
            entry.setHash(hash_val);
            entry.setKey(key);
            entry.setValue(value);
            entry.setNext(
    this.bins[bin_pos]);
            
    this.bins[bin_pos] = entry;
            
    this.num_entries++;
        }

        
    private StTableEntry<T, V> findEntry(int hash_val, T key) {
            
    int bin_pos = hash_val % this.num_bins;
            StTableEntry
    <T, V> entry = this.bins[bin_pos];
            
    if (entryNotEqual(entry, key, hash_val)) {
                entry 
    = entry.next;
                
    while (entryNotEqual(entry, key, hash_val)) {
                    entry 
    = entry.next;
                }
            }
            
    return entry;
        }

        
    // 判斷元素是否相同
        private boolean entryNotEqual(StTableEntry<T, V> entry, T key, int hash_val) {
            
    return entry != null
                    
    && (entry.getHash() != hash_val || (!key.equals(entry.getKey())));
        }

    }

      單元測試類就不列了,給一個與HashMap的簡單性能對比,以整型為鍵,顯然StTable快多了,對于字符串型,關(guān)鍵是HashFunction的定義,我直接調(diào)用String的hashCode方法,不知道有沒有其他更好的方法讓元素分布的更均勻些:
    import java.util.HashMap;
    import java.util.Map;

    public class Benchmark {
        
    public static void main(String args[]) {
           
    long map_cost = testStringMap();
            
    long table_cost = testStringTable();
            
    if (map_cost <= table_cost)
                System.out.println(
    "map is faster than table ");
            
    else
                System.out.println(
    "table is faster than map ");

            map_cost 
    = testIntegerMap();
            table_cost 
    = testIntegerTable();
            
    if (map_cost <= table_cost)
                System.out.println(
    "map is faster than table ");
            
    else
                System.out.println(
    "table is faster than map ");
        }

        
    public static long testIntegerMap() {
            Map
    <Integer, Integer> map = new HashMap<Integer, Integer>();
            
    long start = System.nanoTime();
            
    for (int i = 0; i < 10000; i++)
                map.put(i, i);
            
    long result = 0;
            
    for (int i = 0; i < 10000; i++)
                result 
    += map.get(i);
            
    long end = System.nanoTime();
            System.out.println(
    "result:" + result);
            System.out.println(
    "map:" + (end - start));
            
    return (end - start);
        }

        
    public static long testIntegerTable() {
            HashFunction
    <Integer> intHash = new HashFunction<Integer>() {
                
    public int hash(Integer key) {
                    
    return key;
                }
            };
            StTable
    <Integer, Integer> table = new StTable<Integer, Integer>(intHash);
            
    long start = System.nanoTime();
            
    for (int i = 0; i < 10000; i++)
                table.put(i, i);
            
    long result = 0;
            
    for (int i = 0; i < 10000; i++)
                result 
    += table.get(i);
            
    long end = System.nanoTime();
            System.out.println(
    "result:" + result);
            System.out.println(
    "table:" + (end - start));
            
    return (end - start);
        }

        
    public static long testStringMap() {
            Map
    <String, String> map = new HashMap<String, String>();
            
    long start = System.nanoTime();
            
    for (int i = 0; i < 10000; i++)
                map.put(String.valueOf(i), String.valueOf(i));
            
    long result = 0;
            
    for (int i = 0; i < 10000; i++)
                result 
    += Integer.parseInt(map.get(String.valueOf(i)));
            
    long end = System.nanoTime();
            System.out.println(
    "result:" + result);
            System.out.println(
    "map:" + (end - start));
            
    return (end - start);
        }

        
    public static long testStringTable() {
            HashFunction
    <String> intHash = new HashFunction<String>() {
                
    int i = 0;
                
    public int hash(String key) {
                    
    int hashCode = key.hashCode();
                    
    return hashCode < 0 ? -hashCode : hashCode;
                }
            };
            StTable
    <String, String> table = new StTable<String, String>(intHash);
            
    long start = System.nanoTime();
            
    for (int i = 0; i < 10000; i++)
                table.put(String.valueOf(i), String.valueOf(i));
            
    long result = 0;
            
    for (int i = 0; i < 10000; i++)
                result 
    += Integer.parseInt(table.get(String.valueOf(i)));
            
    long end = System.nanoTime();
            System.out.println(
    "result:" + result);
            System.out.println(
    "table:" + (end - start));
            
    return (end - start);
        }

    }

    結(jié)果為:
    result:49995000
    map:55501468
    result:49995000
    table:60999652
    map is faster than table

     
    result:49995000
    map:44634444
    result:49995000
    table:26209477
    table is faster than map

    將get換成remove方法,結(jié)果也與上面的類似。



    主站蜘蛛池模板: 四虎影视大全免费入口| 一级毛片成人免费看a| 亚洲最大的视频网站| 亚洲AV无码专区亚洲AV伊甸园| 亚洲自偷自偷在线制服| 亚洲人色婷婷成人网站在线观看| 亚洲一区二区三区在线播放| 亚洲国产中文字幕在线观看| 亚洲国产精品成人| 精品国产亚洲男女在线线电影 | 国产大片免费网站不卡美女| 国产好大好硬好爽免费不卡 | 国产精品亚洲精品日韩电影| 美女又黄又免费的视频| 一级美国片免费看| 香蕉免费看一区二区三区| 99久久国产精品免费一区二区| 久久这里只精品国产免费10| 四虎免费影院ww4164h| 国产在线观看片a免费观看| 最新69国产成人精品免费视频动漫| 国产美女精品视频免费观看| 亚洲国产精品尤物yw在线| 久久亚洲国产成人影院网站| 亚洲AV永久精品爱情岛论坛| 亚洲白嫩在线观看| 亚洲AV无码成人网站在线观看| 九九久久国产精品免费热6| 国内精品久久久久影院免费| 国产成人精品免费视频网页大全| 精品剧情v国产在免费线观看| 亚洲精品无码你懂的网站| 久久亚洲成a人片| 亚洲乱码在线卡一卡二卡新区| 无码天堂va亚洲va在线va| a毛片全部播放免费视频完整18| 最近的中文字幕大全免费8| 四虎影院在线免费播放| 中国亚洲女人69内射少妇| 91在线亚洲精品专区| 色婷婷六月亚洲综合香蕉|