我模仿lucene的BytesRef写了一个CharsRefIntHashMap,实測效果并不如HashMap<String, Integer>。代码例如以下:

package com.dp.arts.lucenex.utils;

import org.apache.lucene.util.CharsRef;

public interface CharsRefIntMap

{

public static
abstract class CharsRefIntEntryAccessor {

public abstract
void access(char[] arr,
int offset, int length,
int value);

}

public void incKey(CharsRef key);

public void incKey(CharsRef key,
int add);

public void incKey(char[] arr,
int offset, int length);

public void incKey(char[] arr,
int offset, int length,
int add);

public int get(CharsRef key);

public int get(CharsRef key,
int no_entry_value);

public int get(char[] arr,
int offset, int length);

public int get(char[] arr,
int offset, int length,
int no_entry_value);

public int size();

public void forEach(CharsRefIntEntryAccessor accesor);

}


package com.dp.arts.lucenex.utils;





import java.util.Arrays;





import org.apache.lucene.util.CharsRef;





import com.dp.arts.lucenex.utils.CharsRefIntMap.CharsRefIntEntryAccessor;





public class CharsRefIntHashMap implements CharsRefIntMap

{

    public static final int DEFAULT_CAPACITY = 16;

    

    private char[][] arrs;

    private int[] offsets;

    private int[] lengths;

    private int[] ords;

    private int[] values;

    

    private int hashSize;

    private int halfHashSize;

    private int hashMask;

    private int count;

    

    public CharsRefIntHashMap() {

        this(DEFAULT_CAPACITY);

    }

    

    public CharsRefIntHashMap(int capacity) {

        assert capacity > 0 && ( (capacity & (capacity - 1)) == 0);

        

        arrs = new char[capacity][];

        offsets = new int[capacity];

        lengths = new int[capacity];

        ords = new int[capacity];

        values = new int[capacity];

        

        Arrays.fill(ords, -1);

        hashSize = capacity;

        halfHashSize = (capacity >>> 1);

        hashMask = capacity - 1;

    }





    @Override

    public void incKey(CharsRef key) {

        int code = charsHashCode(key.chars, key.offset, key.length);

        incKey(key.chars, key.offset, key.length, code, 1);

    }





    @Override

    public void incKey(CharsRef key, int add) {

        int code = charsHashCode(key.chars, key.offset, key.length);

        incKey(key.chars, key.offset, key.length, code, add);

    }





    @Override

    public void incKey(char[] arr, int offset, int length) {

        int code = charsHashCode(arr, offset, length);

        incKey(arr, offset, length, code, 1);

    }

    

    @Override

    public void incKey(char[] arr, int offset, int length, int add) {

        int code = charsHashCode(arr, offset, length);

        incKey(arr, offset, length, code, add);

    }

    

    private void incKey(char[] arr, int offset, int length, int code, int add) {

        int pos = (code & hashMask);

        int e = ords[pos];

        while (e != -1 && !charsEquals(arrs[e], offsets[e], lengths[e], arr, offset, length)) {

            final int inc = ((code >> 8) + code) | 1;

            code += inc;

            pos = (code & hashMask);

            e = ords[pos];

        }

        if (e == -1) {

            // new entry.

            arrs[count] = arr;

            offsets[count] = offset;

            lengths[count] = length;

            values[count] = add;

            ords[pos] = count;

            ++count;

            if (count == halfHashSize) {

                rehash((hashSize << 1));

            }

        } else {

           values[e] += add;

        }

    }

    

    private void rehash(int newSize) {

        char[][] newArrs = new char[newSize][];

        int[] newOffsets = new int[newSize];

        int[] newLengths = new int[newSize];

        int[] newValues = new int[newSize];

        System.arraycopy(arrs, 0, newArrs, 0, halfHashSize);

        System.arraycopy(offsets, 0, newOffsets, 0, halfHashSize);

        System.arraycopy(lengths, 0, newLengths, 0, halfHashSize);

        System.arraycopy(values, 0, newValues, 0, halfHashSize);





        final int[] newOrds = new int[newSize];

        Arrays.fill(newOrds, -1);

        final int newHashMask = newSize - 1;

        for (int i = 0; i < hashSize; ++i) {

            int e0 = ords[i];

            if (e0 != -1) {

                char[] arr = newArrs[e0];

                int offset = newOffsets[e0];

                int length = newLengths[e0];

                int code = charsHashCode(arr, offset, length);

                int pos = code & newHashMask;

                while (newOrds[pos] != -1) {

                    final int inc = ((code >> 8) + code) | 1;

                    code += inc;

                    pos = code & newHashMask;

                }

                newOrds[pos] = e0;

            }

        }

        

        ords = newOrds;

        arrs = newArrs;

        offsets = newOffsets;

        lengths = newLengths;

        values = newValues;

        

        hashSize = newSize;

        halfHashSize = (newSize >> 1);

        hashMask = newHashMask;

    }

    

    public int charsHashCode(char[] chars, int offset, int length) {

        final int prime = 31;

        int result = 0;

        final int end = offset + length;

        for (int i = offset; i < end; i++) {

          result = prime * result + chars[i];

        }

        return result;

    }

    

    public boolean charsEquals(char[] lhsArr, int lhsOffset, int lhsLength, char[] rhsArr, int rhsOffset, int rhsLength) {

        if (lhsLength == rhsLength) {

          int otherUpto = rhsOffset;

          final int end = lhsOffset + lhsLength;

          for (int upto = lhsOffset; upto < end; upto++, otherUpto++) {

            if (lhsArr[upto] != rhsArr[otherUpto]) {

              return false;

            }

          }

          return true;

        } else {

          return false;

        }

    }

    

    @Override

    public int get(CharsRef key) {

        return get(key.chars, key.offset, key.length, 0);

    }

    

    @Override

    public int get(CharsRef key, int no_entry_key) {

        return get(key.chars, key.offset, key.length, no_entry_key);

    }

    

    @Override

    public int get(char[] arr, int offset, int length) {

        return get(arr, offset, length, 0);

    }

    

    @Override

    public int get(char[] arr, int offset, int length, int no_entry_key) {

        int code = charsHashCode(arr, offset, length);

        int pos = (code & hashMask);

        int e = ords[pos];

        while (e != -1 && !charsEquals(arrs[e], offsets[e], lengths[e], arr, offset, length)) {

            final int inc = ((code >> 8) + code) | 1;

            code += inc;

            pos = (code & hashMask);

            e = ords[pos];

        }

        return e == -1 ? no_entry_key : values[e];

    }

    

    @Override

    public void forEach(CharsRefIntEntryAccessor accessor) {

        for (int i = 0; i < hashSize; ++i) {

            int pos = ords[i];

            if (pos != -1) {

                accessor.access(arrs[pos], offsets[pos], lengths[pos], values[pos]);

            }

        }

    }





    @Override

    public int size() {

        return count;

    }

    

    // for test only.

    public int hashSize() {

        return hashSize;

    }

}

package com.dp.arts.lucenex.utils;

import java.util.HashMap;

import java.util.Random;

import
org.apache.lucene.util.CharsRef;

public class CharsRefIntHashMapBenchmark

{

private static Random
randGen = null;

private
static char[]
numbersAndLetters =
null;

static {

randGen =
new Random();

numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" +

"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();

}

private static
final String randomString(int length) {

if (length < 1) {

return
null;

}

char [] randBuffer =
new char[length];

for (int i=0; i<randBuffer.length; i++) {

randBuffer[i] = numbersAndLetters[randGen.nextInt(71)];

}

return new String(randBuffer);

}

public static
void main(String[] args) {

final int MAX = 100000;

String[] strs = new String[10000];

int[] values =
new int[MAX];

for (int i = 0; i < 10000; ++i) {

strs[i] = randomString(randGen.nextInt(10) + 1);

}

for (int i = 0; i < MAX; ++i) {

values[i] = randGen.nextInt(10000);

}

char[][] arrs =
new char[MAX][];

int offsets[] =
new int[MAX];

int counts[] =
new int[MAX];

for (int i = 0; i < MAX; ++i) {

String s = strs[values[i]];

arrs[i] = StringMisc.toCharArray(s);

offsets[i] = StringMisc.getOffset(s);

counts[i] = StringMisc.getCount(s);

}

long start = System.currentTimeMillis();

CharsRefIntHashMap map = new CharsRefIntHashMap();

for (int j = 0; j < 100; ++j) {

for (int i = 0; i < MAX; ++i) {

map.incKey(arrs[i], offsets[i], counts[i]);

}}

System.err.println("CharsRefIntHashMap time elapsed: " + (System.currentTimeMillis() - start) +
"ms.");

start = System.currentTimeMillis();

HashMap<String, Integer> oldMap = new HashMap<String, Integer>();

for (int j = 0; j < 100; ++j) {

for (int i = 0; i < MAX; ++i) {

String s = strs[values[i]];

Integer v = oldMap.get(s);

if (v ==
null) {

v = new Integer(1);

oldMap.put(s, v);

} else {

v += 1;

}

}}

System.err.println("Origin string map time elapsed: " + (System.currentTimeMillis() - start) +
"ms.");

}

}


因此这样写优点不过内存少用一些,性能应该更差,rehash时须要拷贝很多其它数据,对每一个数据的訪问都须要下标。实际情况下,CharsRef所须要的内存是24字节。假设使用trove的TObjectIntHashMap,插入速度相当,查询速度是jdk hashmap的三倍。

CharsRefIntHashMap并不比HashMap&lt;String, Integer&gt;快的更多相关文章

  1. string integer == equals 转

    java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boolean   他们之间的比较,应用双等号(== ...

  2. String,Integer,int类型之间的相互转换

    String, Integer, int 三种类型之间可以两两进行转换 1. 基本数据类型到包装数据类型的转换 int -> Integer (两种方法) Integer it1 = new I ...

  3. Junit + String/Integer/ArrayList/HashMap/TreeMap 基本使用Demo

    package JavaTest.test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; ...

  4. List<Map<String, Integer>> 同key的value全部累加合并

    public static void main(String[] args){ List<Map<String,Object>> list1 = new ArrayList&l ...

  5. Delphi out 参数 string Integer

    http://www.delphibasics.co.uk/RTL.asp?Name=Out http://stackoverflow.com/questions/14507310/whats-the ...

  6. string(Integer)类的equals和==区别和联系(验证密码的时候用得到)

    “==”在八种原始数据类型中,判断的是两边的值是否相等.对于对象类型来说,判断的是内存地址,所以为true所满足的条件就是两边的引用指向同一个对象. 比如String s1 = "abcde ...

  7. java方法笔记: split,instanceof,StringBuilder(),append(),string ,Integer,Math,正则表达式

    http://swiftlet.net/archives/709 如果分隔符在前方,会显示“”,在尾部不显示: *|做分割,需要加\\ API文档如下 1.instanceof 查看前者是否是后者的实 ...

  8. Java String Integer转换 练习:编程求字符串“100”和“150”按十进制数值做差后的结果以字符串形式输出。

    package com.swift; public class String_To_Integer_Test { public static void main(String[] args) { /* ...

  9. Map<String,Integer>acount字符串出现的次数

随机推荐

  1. 剑指offer笔记

    1.在定义类的赋值描述符成员函数时,有以下几点要注意: 1)判断是否是自己赋值给自己 2)返回值是const类的引用(为了连续赋值) 3)参数是const类的引用 4)如果数据成员中有指针,注意要深拷 ...

  2. SyntaxError: EOL while scanning string literal的解决

    2281 python中字符串的最后一个字符是斜杠会导致出错:SyntaxError: EOL while scanning string literal [背景] Python 2.7.2 中想要通 ...

  3. C - Domino piling

    Problem description You are given a rectangular board of M × N squares. Also you are given an unlimi ...

  4. D - Garden

    Problem description Luba thinks about watering her garden. The garden can be represented as a segmen ...

  5. java热部署

    最近使用java做项目,研究了一下热部署,能够提高工作效率. 需要准备的工具: 1.安装文件http://update.zeroturnaround.com/update-site/ 2.破解 下载破 ...

  6. informix 通过ADO或ODBC连接提取数据时出现中文乱码的解决方法

    最近在做一个项目,是对INFORMIX数据库的数据进行大数据分析,INFORMIX数据库数据有上亿条,没有linux的Root权限和informix数据的生产权限,只能读取.客户要求结果显示在内网wi ...

  7. Java 开源博客 Solo 1.2.0 发布 - 一键启动

    Solo 1.2.0 正式发布了,感谢一直以来关注 B3log 开源的朋友! 在这个版本中,我们引入了一个新的特性 -- 独立模式: 不需要安装数据库.Servlet 容器 只需要安装好 Java 环 ...

  8. 苹果双系统win8.1遇到的一些问题

    MacBook air是一款不错的电脑,详细没研究就不叙述好与坏了.只此记录自己使用这款笔记本遇到的问题. 一.安装双系统win8.1 1.下载镜像文件—>拷贝到ios内存中,一个8GU盘.ht ...

  9. css下拉菜单写法

    网页导航栏的下拉效果,通过div框的显示和隐藏实现. <html> <head> <meta charset="UTF-8"> <titl ...

  10. Clustered Index Scan 与 Clustered Index Seek

    Clustered Index Scan 与 Clustered Index Seek 在利用 SQL Server 查询分析器的执行计划中,会有许多扫描方式,其中就有 Clustered Index ...