![](/img/trans.png)
[英]What's the most efficient way to bulk-copy to SQL Server from Java?
[英]Create a HashMap copy in Java - What's the most efficient way?
我有一个HashMap需要复制~100000次,副本将单独扩展。 由于100 000个副本很多(这不是我的代码中唯一发生的时间),这是我实现的一个主要瓶颈(事实上,它经常发生,占用了45%的运行时间,并且有不幸的是没有办法限制这个数字),所以我正在寻找最有效的方法来做到这一点。
我找到了以下选项来创建HashMap原始的浅表副本:
//1
HashMap<T> map = (HashMap<T>) original.clone()
和
//2
HashMap<T> map = new HashMap<T>();
map.putAll(original);
和
//3
HashMap<T> map = new HashMap<T>(original);
根据您的经验,复制HashMap最有效的方法是什么? 有没有我错过的选项(除了通过原始的迭代,但我想这不是一个真正的选项)?
考虑一下你是否真的需要副本。
你说“我只需要具有相同对象的地图,我可以单独添加其他对象而不影响其他地图”。 考虑到这一点,您可以创建Map
的复合实现:
class MyCompositeMap<K, V> implements Map<K, V> {
final Map<K, V> mapThatYouAddThingsTo;
final Map<K, V> mapThatIsShared;
}
现在,您可以实现您的方法。 例如:
containsKey
方法可以先检查mapThatYouAddThingsTo
以查看该键是否存在; 如果是这样,它将从mapThatYouAddThingsTo
返回值。 否则,它会检查mapThatIsShared
。 put
方法只会把东西放到mapThatYouAddThingsTo
,永远不会放入mapThatIsShared
。 实现有一些棘手的方面(比如重复删除keySet()
和entrySet()
的键和值),但是如果mapThatYouAddThingsTo
比mapThatIsShared
,那么你将使用更少的内存。
1 - 这是最糟糕的。 2和3几乎相同。 您正在使用Map,它也被视为一个集合。 为什么克隆不好的做法你可以在这里阅读: 为什么人们如此害怕使用clone()(在集合和JDK类上)?
我会选择这个:
HashMap<T> map = new HashMap<T>(original);
,因为当API让你能够更优雅地编写它时 - 通常api会以最恰当的方式处理场景背后的其他事情。
这是一个老问题,但我认为还有其他事情要提。
如果您只想创建地图的浅表副本,则最推荐使用选项编号3。
但是,如果您需要制作定义为HashMap<Integer, List<Item>>
的地图副本,但您希望在更改副本中的内容时原始地图保持不变。 即,如果从副本中的List中删除某些内容,则原始中的List应保持该值。
我有两个解决方案,这是一个深度复制功能。 目前Java 8不提供本机实现。 我们可以使用Guava或Apache Commons Lang 。 但是我们可以找到一个创建使用foreach
方法或Stream.collect()
方法创建新实例的方法的工作。 前者很简单,我们使用foreach来创建一个新的实例,我们要复制的对象在这种情况下为List<T>
在这里检查泛型函数:
public static <T> HashMap<Integer, List<T>> deepCopy(HashMap<Integer, List<T>> original)
{
HashMap<Integer, List<T>> copy = new HashMap<>();
for (Map.Entry<Integer, List<T>> entry : original.entrySet()) {
copy.put(entry.getKey(), new ArrayList<>(entry.getValue()));
}
return copy;
}
如果您不想处理泛型,那么我们将使用Stream.collect()
。 在这种情况下,我们使用流来提取数据,并将其包装为地图并创建新实例
public static <T> Map<Integer, List<T>> deepCopyStream(Map<Integer, List<T>> original)
{
return original
.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, valueMapper -> new ArrayList<>(valueMapper.getValue())));
}
请注意,我没有使用<K,V>
作为泛型,因为这不是一个适当的深层复制方法,它将适用于每个级别的嵌套克隆。 这种方法基于我们有一个HashMap<Integer, List<Item>>
的想法,其中Item
类不包含需要克隆的属性。
你需要遍历项目。 最简单的方法是Stream。 我为地图创建了一个字符串,并为你的“T”制作了一个“Pojo”类......
public void testMapCopy() {
// build the orig map
Map<String, Pojo> orig = new HashMap();
for (int i = 0; i < 10; i++) {
orig.put("k" + i, new Pojo("v"+i));
}
// make a copy
Map<String, Pojo> mapCopy = orig.entrySet().stream()
.collect(Collectors.toMap(e -> e.getKey(), new Pojo(e.getValue().getValue())));
// change orig
Pojo pojo = orig.get("k0");
pojo.setValue("v0-updated!");
// check values
System.out.println("orig k0: " + orig.get("k0").getValue());
System.out.println("copy k0: " + mapCopy.get("k0").getValue());
}
简单的类代表你的“T”
private class Pojo {
private String value;
public Pojo(String value) {
this.value = value;
}
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.