Java Dictionary - 将int值分配给字符串

时间:2014-05-10 18:20:02

标签: java map concurrency performance

很抱歉,如果这看起来像一个简单的问题,但我需要存储6000万条记录,其中包含总共200万个不同的字符串。在6000万条记录中,我想存储字符串的整数表示,因此当我加载记录时,我将为它们分配一个整数

e.g。 如果我的输入是a,b,c,a 然后我将存储1,2,3,1

将以多个线程读取和提交记录。我提出了以下几点,从提高效率的角度来看,我能做出哪些改进?

编辑:我将构建拥有多达200万个密钥的地图。如果我不这样做,我将不得不使用字符串。我使用Trove的TIntHashMap采用以下方法,我的性能要好得多

非常感谢,

private final Map<String, Integer> stringDictionary = new HashMap<>(2000000);

private int index = 0;

private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

public int getStringCodeIntegerValue(String stringCode) {
    readWriteLock.readLock().lock();
    Integer result = stringDictionary.get(stringCode);
    if (result == null) {
        // Must release read lock before acquiring write lock
        readWriteLock.readLock().unlock();
        readWriteLock.writeLock().lock();
        try {
            result = stringDictionary.get(stringCode);
            if (result == null) {
                stringDictionary.put(stringCode, ++index);
                result = stringDictionary.get(stringCode);
            }
            // Downgrade by acquiring read lock before releasing write lock
            readWriteLock.readLock().lock();
        } finally {
            readWriteLock.writeLock().unlock(); // Unlock write, still hold read
        }
    }
    readWriteLock.readLock().unlock();
    return result;
}

2 个答案:

答案 0 :(得分:0)

首先,听起来好像你正试图重新发明内部字符串?您有什么理由不能使用作为问题标准提供的实习字符串吗?

http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#intern--

其次,如果您确实需要自己执行此操作,而不是在HashMap之上分层自己的锁定策略,那么您最好使用ConcurrentHashMap,这可以提供支持多个并发写作者。

在评论中回答您的问题,这里是执行getStringCodeIntegerValue的一种方式(未经测试,但我有理由相信它是对的 - {{1的功能几乎就是你想要的东西):

putIfAbsent

此实现可能会导致索引值被丢弃&#34;如果两个线程都试图同时添加相同的字符串,但我不相信这对你来说应该是一个问题。

说完所有这些后,如果您已根据标准地图测试了自己的实施情况,并且效果更好,则表明final AtomicInteger index = new AtomicInteger(); final ConcurrentHashMap<String, Integer> stringDictionary = new ConcurrentHashMap<String, Integer>(); public int getStringCodeIntegerValue(String stringCode) { Integer result = stringDictionary.get(stringCode); if (result != null) return result; else return stringDictionary.putIfAbsent(stringCode, index.incrementAndGet()); } 的并发更新不是问题对于你的特定使用模式,所以也许你应该坚持你所拥有的?

说完那个后,对我来说仍然听起来好像你正在尝试重新发明实习词。为什么你不能使用实习字符串 - 它们听起来就像你需要的那样?

答案 1 :(得分:0)

在阅读你的评论后,我仍然不清楚你想要实现的目标。

但是,您可以生成字符串的整数摘要(字符串可以是任意长度)。例如SHA1或MD5。您可以使用Apache Commons DigestUtils

然后您可以为每个字符串存储摘要和物理字符串,但是使用SHA1 / MD5列将帮助您通过摘要索引数据并更快地访问记录。

请记住,摘要是不可逆的,即您无法从摘要中重现原始字符串。

希望它有所帮助!