为了账号安全,请及时绑定邮箱和手机立即绑定

如何克隆ArrayList和复制其内容?

如何克隆ArrayList和复制其内容?

斯蒂芬大帝 2019-06-03 17:14:55
如何克隆ArrayList和复制其内容?我如何克隆ArrayList也用Java克隆它的项目?例如,我有:ArrayList<Dog> dogs = getDogs();ArrayList<Dog> clonedList = ....something to do with dogs....我希望在clonedList和狗的名单不一样。
查看完整描述

4 回答

?
噜噜哒

TA贡献1784条经验 获得超7个赞

您将需要对项目进行迭代,并逐一克隆它们,并在执行过程中将克隆放入结果数组中。

public static List<Dog> cloneList(List<Dog> list) {
    List<Dog> clone = new ArrayList<Dog>(list.size());
    for (Dog item : list) clone.add(item.clone());
    return clone;}

很明显,要想让它起作用,你必须得到你的Dog类实现Cloneable接口并覆盖clone()方法。


查看完整回答
反对 回复 2019-06-03
?
互换的青春

TA贡献1797条经验 获得超6个赞

就我个人而言,我想在Dog中添加一个构造函数:

class Dog{
    public Dog()
    { ... } // Regular constructor

    public Dog(Dog dog) {
        // Copy all the fields of Dog.
    }}

然后只需迭代(如Varkhan的答案所示):

public static List<Dog> cloneList(List<Dog> dogList) {
    List<Dog> clonedList = new ArrayList<Dog>(dogList.size());
    for (Dog dog : dogList) {
        clonedList.add(new Dog(dog));
    }
    return clonedList;}

我发现这样做的好处是,您不需要在Java中乱搞破克隆的东西。它还与复制Java集合的方式相匹配。

另一种选择是编写自己的ICloneable接口并使用它。这样,您就可以编写一个用于克隆的通用方法。


查看完整回答
反对 回复 2019-06-03
?
青春有我

TA贡献1784条经验 获得超8个赞

所有标准集合都有副本构造函数。用它们。

List<Double> original = // some listList<Double> copy = new ArrayList<Double>(original); //This does a shallow copy

clone()设计时有几个错误(请参阅这个问题),所以最好避免它。

从…有效Java第二版,项目11:明智地覆盖克隆

考虑到与cloneable相关的所有问题,可以肯定地说,其他接口不应该扩展它,为继承而设计的类(项目17)不应该实现它。由于它的许多缺点,一些专业的程序员只是选择永远不覆盖克隆方法,从来不调用它,也许,除了复制数组。如果为继承设计类,请注意,如果选择不提供行为良好的受保护的克隆方法,子类不可能实现cloneable。

本书还描述了复制构造器相对于克隆/克隆具有的许多优点。

  • 他们不依赖于一种易受风险的语言外对象创建机制。
  • 它们并不要求对文件很少的公约进行强制执行。
  • 它们与最终字段的正确使用没有冲突
  • 它们不会抛出不必要的检查异常
  • 他们不需要石膏。

考虑使用复制构造函数的另一个好处:假设您有一个HashSet s,而您希望将其复制为TreeSet..克隆方法不能提供此功能,但使用转换构造函数很容易:new TreeSet(s).


查看完整回答
反对 回复 2019-06-03
?
慕森王

TA贡献1777条经验 获得超3个赞

Java 8提供了一种新的方法来调用元素狗上的复制构造函数或克隆方法:溪流兰巴斯收藏家.

复制构造函数:

List<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toList());

表达Dog::new称为a方法参考..它创建一个函数对象,该对象调用Dog以另一只狗为论据。

克隆方法[1]:

List<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList());

得到一个ArrayList结果

或者,如果你必须得到一个ArrayListBack(万一您以后想修改它):

ArrayList<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toCollection(ArrayList::new));

更新列表

如果不需要保留dogs列表,您可以使用replaceAll方法并更新列表:

dogs.replaceAll(Dog::new);

所有的例子都假设import static java.util.stream.Collectors.*;.


收集器ArrayLists

上一个示例中的收集器可以变成util方法。既然这是一件很平常的事,我个人喜欢它又短又漂亮。就像这样:

ArrayList<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toArrayList());public static <T>
 Collector<T, ?, ArrayList<T>> toArrayList() {
    return Collectors.toCollection(ArrayList::new);}

[1]关于CloneNotSupportedException:

若要使此解决方案运行在clone方法Dog 绝不能宣布它抛出CloneNotSupportedException..原因是map不允许抛出任何已检查的异常。

就像这样:

    // Note: Method is public and returns Dog, not Object
    @Override
    public Dog clone() /* Note: No throws clause here */ { ...

不过,这不应该是个大问题,因为这是最好的做法。(效果Java例如,给出这个建议。)

感谢古斯塔沃注意到这一点。


PS:

如果您发现它更漂亮,您可以使用方法引用语法来做完全相同的事情:

List<Dog> clonedDogs = dogs.stream().map(Dog::clone).collect(toList());


查看完整回答
反对 回复 2019-06-03
  • 4 回答
  • 0 关注
  • 2312 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号