我遇到了一个场景,我想将 HashMap 的所有键都小写(不要问为什么,我只是必须这样做)。 HashMap 有数百万个条目。
起初,我以为我只是创建一个新的 Map,迭代要小写的映射条目,然后添加相应的值。这个任务应该每天只运行一次或类似的东西,所以我想我可以忍受这个。
Map<String, Long> lowerCaseMap = new HashMap<>(myMap.size());
for (Map.Entry<String, Long> entry : myMap.entrySet()) {
lowerCaseMap.put(entry.getKey().toLowerCase(), entry.getValue());
}
然而,当我准备复制地图时我的服务器超载时,这导致了一些 OutOfMemory 错误。
现在我的问题是,如何以最小的内存占用完成这个任务?
是否会删除小写后的每个键 - 添加到新的地图帮助中?
我可以利用 java8 流来加快速度吗? (例如这样的东西)
Map<String, Long> lowerCaseMap = myMap.entrySet().parallelStream().collect(Collectors.toMap(entry -> entry.getKey().toLowerCase(), Map.Entry::getValue));
更新 看来这是一个
Collections.unmodifiableMap
所以我没有的选项
删除小写后的每个键 - 添加到新地图
您可以尝试使用不区分大小写的
HashMap
,而不是使用 TreeMap
。这将避免需要创建每个密钥的小写版本:
Map<String, Long> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
map.putAll(myMap);
String.CASE_INSENSITIVE_ORDER
是一个 Comparator
,它对字符串进行不区分大小写的比较。构建此映射后,put()
和get()
将不区分大小写,因此您可以使用全小写键保存和获取值。迭代键将返回它们的原始形式,可能是大写形式。
以下是一些类似的问题:
迭代地图时无法删除条目。如果您尝试这样做,您将遇到 ConcurentModificationException。
由于问题是 OutOfMemoryError,而不是性能错误,因此使用并行流也无济于事。
尽管最近将完成 Stream API 上的一些任务,但这仍然会导致内存中在某些时候有两个映射,因此您仍然会遇到问题。
为了解决这个问题,我只看到了两种方法:
对于分割算法,您可以使用 Stream API 尝试类似的操作:
Map<String, String> toMap = new HashMap<>();
int chunk = fromMap.size() / 10;
for(int i = 1; i<= 10; i++){
//process the chunk
List<Entry<String, String>> subEntries = fromMap.entrySet().stream().limit(chunk)
.collect(Collectors.toList());
for(Entry<String, String> entry : subEntries){
toMap.put(entry.getKey().toLowerCase(), entry.getValue());
fromMap.remove(entry.getKey());
}
}
上述答案中的担忧是正确的,您可能需要重新考虑更改您正在使用的数据结构。
对我来说,我有一个简单的地图,我需要将其键更改为小写
看看我的代码片段,它是一个微不足道的解决方案,而且性能很差
private void convertAllFilterKeysToLowerCase() {
HashSet keysToRemove = new HashSet();
getFilters().keySet().forEach(o -> {
if(!o.equals(((String) o).toLowerCase()))
keysToRemove.add(o);
});
keysToRemove.forEach(o -> getFilters().put(((String) o).toLowerCase(), getFilters().remove(o)));
}
不确定内存占用。如果使用 Kotlin,您可以尝试以下操作。
val lowerCaseMap = myMap.mapKeys { it.key.toLowerCase() }
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/map-keys.html