【问题标题】:I have two lists containing the same objects. How do I change one list without changing the other? [duplicate]我有两个包含相同对象的列表。如何更改一个列表而不更改另一个? [复制]
【发布时间】:2016-10-31 11:07:40
【问题描述】:
当我只将对象放在 listOfRates 中,然后通过复制它创建 inverseListOfRates 时,我首先注意到了这个问题。但即使使用这种方法,我也无法在不更改另一个列表的情况下更改一个列表。
我该如何解决这个问题?
List<HistoricRate> listOfRates = new ArrayList<HistoricRate>();
List<HistoricRate> inverseListOfRates = new ArrayList<HistoricRate>();
for (HistoricRate rate : rates){
listOfRates.add(rate);
inverseListOfRates.add(rate);
}
inverseListOfRates.forEach(r -> r.setMid(1 / r.getMid()));
【问题讨论】:
标签:
java
list
object
deep-copy
shallow-copy
【解决方案1】:
这两个列表引用同一个对象。所以如果你改变第一个,第二个也会改变。
解决方案是在将对象添加到第二个列表之前克隆对象(将其复制到新实例中)。
要克隆对象,您可以使用以下建议之一:
1- 复制构造函数:
class HistoricRate {
private String field;
public HistoricRate (HistoricRate another) {
this.field= another.field; // you can access
}
}
2- HistoricRate 必须实现 Cloneable 接口
实现方法clone来复制对象。
3- 使用 org.apache.commons.lang.SerializationUtils 如下:
for (HistoricRate rate : rates){
listOfRates.add(rate);
inverseListOfRates.add(SerializationUtils.clone(rate));
}
【解决方案2】:
您需要熟悉浅拷贝与深拷贝。
由于两个数组列表都指向堆上完全相同的对象,因此您的数组看起来像这样
当您修改其中一个速率圈(对象)时,由于另一个列表在其相应索引中指向完全相同的事物,因此它将看到您对另一个列表所做的更改。
您需要为 HistoricRate 类定义一个复制构造函数:
public HistoricRate(HistoricRate other){
this.data = other.data;
//copy the other instance variables here
}
然后当您将 HistoricRate 添加到您的列表中时,您可以添加
listOfRates.add(new HistoricRate( currentRate ) );
由于您使用的是“新”,因此列表将接收新对象,并且对其中一个的更改不会影响另一个。它看起来像这样: