很抱歉,如果这看起来像一个简单的问题,但我需要存储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;
}
答案 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列将帮助您通过摘要索引数据并更快地访问记录。
请记住,摘要是不可逆的,即您无法从摘要中重现原始字符串。
希望它有所帮助!