我有两个包含相同对象的列表。如何在不更改另一个列表的情况下更改一个列表?

I have two lists containing the same objects. How do I change one list without changing the other?

当我只将对象放入 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()));

这两个列表引用了同一个对象。所以如果你改变第一个,第二个也会改变。

解决方案是在将对象添加到第二个列表之前克隆该对象(将其副本创建到新实例中)。

要克隆对象,您可以使用以下建议之一:

1- 复制的构造函数:

class HistoricRate {
  private String field;

  public HistoricRate (HistoricRate another) {
    this.field= another.field; // you can access  
  }
}

2- HistoricRate 必须实现 Cloneable 接口

执行克隆方法复制对象。

3- 使用 org.apache.commons.lang.SerializationUtils 如下:

for (HistoricRate rate : rates){
    listOfRates.add(rate);
    inverseListOfRates.add(SerializationUtils.clone(rate));
}

您需要熟悉浅拷贝与深拷贝。

由于两个数组列表都指向堆上完全相同的对象,因此您的数组看起来像这样

当您修改其中一个汇率圈(对象)时,由于另一个列表在其相应索引中指向完全相同的内容,因此它将看到您对另一个列表所做的更改。

您需要为 HistoricRate class 定义一个复制构造函数:

public HistoricRate(HistoricRate other){
 this.data = other.data;
 //copy the other instance variables here
}

然后当您将 HistoricRate 添加到您的列表时,您可以添加

listOfRates.add(new HistoricRate( currentRate ) );

由于您使用的是 'new',列表将接收新对象并且对一个对象的更改不会影响另一个。它看起来像这样: