1

我实现了此处描述的复制构造函数。但问题仍然是,当我更新时route_copy,同样的更新也适用于route. 所以,我不明白我的代码有什么问题?

public class Route implements Comparable<Route> {
    private List<Site> sites;

    public Route()
    {
        sites = new ArrayList<Site>();
    }

    public Route(List<Site> sites)
    {
        this.sites = sites;
    }

    /**
     * Copy constructor
     */
    public Route(Route r) {
        this(r.sites);
    }

    public void deleteSite(Site s) {
        this.sites.remove(s);
    }
}

public processData(Route route)
{
  Route route_copy = new Route(route);
  Site s = selectSite(route_copy);
  route_copy.deleteSite(s); // !!! now 'route' does not contain an  element 's'
}
4

5 回答 5

5

在你的复制构造函数中,你只是在做一个浅拷贝,而你需要做一个深拷贝:

public Route(Route r) {
    this(r.sites);
}

在这里,您仍然在复制 的引用list,它仍然指向同一个ArrayList。您也应该修改它以创建列表的副本。可能,您还需要在 arraylist 中创建元素的副本,如下所示:

public Route(Route r) {
    List<Site> newSites = new ArrayList<Site>();

    for (Site obj: r.sites) {
        // Add copy of obj to the newSites
        // So you need yet another copy constructor in 'Site' class.
    }

    this.sites = newSites;
}

检查这篇文章 -浅拷贝与深拷贝。

于 2013-07-17T14:52:06.770 回答
2

您的“复制构造函数”没有复制输入列表。尝试类似的东西

public Route(List<Site> sites)
{
    this.sites = new ArrayList<Site>(sites);
}

为您的第二个构造函数。

于 2013-07-17T14:52:49.700 回答
2

当然,它会创建依赖副本,也称为副本。

你需要一个拷贝。

于 2013-07-17T14:53:02.567 回答
2

问题是两个列表仍然指向相同的内存位置,因此,一个列表上的任何操作最终都会修改另一个列表。

您可以尝试使用 ArrayList 的复制构造函数:

公共 ArrayList(集合 c)

按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表。

像这样:

     public Route(Route r) {
     this(new ArrayList<Site>(r.sites));
     }

但是请注意,Site对列表中的对象进行任何修改可能会对存储在另一个列表中的其他对象产生影响,具体取决于您的Site对象的复杂程度。

于 2013-07-17T14:53:15.953 回答
1

你对复制构造函数所做的只是让新Route的使用旧的列表,Route因此对其中一个的任何更改都会立即影响另一个

您需要做的是让复制构造函数创建一个新列表:

sites = new ArrayList<Site>(oldList);
于 2013-07-17T14:52:57.337 回答