Dart| Flutter :克隆或复制列表的多种方法及实例

2,730 阅读4分钟

克隆是一个对象的副本。一般来说,Clone有两种类型。

让我们在dart中创建一个列表。

  List original = [1, 2, 3];

在创建列表对象时,它做了以下事情。

  • 为列表创建一个变量,即对象

  • 列表数据被存储在内存位置

  • 对象(原始)有一个对内存位置的引用

  • 浅层克隆。在这个复制过程中,数据存在于相同的内存位置,但创建了两个指向相同内存位置的引用。如果你添加或更新原始列表,变化可以在克隆对象中得到。

  • 深度克隆:在克隆过程中,存在两个对象(原始对象和克隆对象)和两个内存位置,每个对象指向不同的内存位置。

如果你添加或更新原始列表,变化不会影响到克隆对象。

如何在dart和flutter中创建一个克隆的列表?

我们有多种方法可以进行浅层和深层克隆。

浅层复制列表

我们有两种方法可以复制引用。

  • 赋值对象:在这个例子中,原始列表被赋值(=)一个新的变量。在这里,修改原始列表在复制的对象中做了改变。

因为赋值运算符允许你用两个对象的引用指向同一个位置。 下面是一个使用赋值运算符的浅层克隆的例子。

void main() {
  List original = [1, 2, 3];
  var cloned = original;
  original.add(5);
  original.remove(2);

  print(original); //[1, 3, 5]
  print(cloned); //[1, 3, 5]
}
  • 使用List casteFrom方法

List casteFrom也会创建一个引用的副本,对原始列表的改变会导致应用原始列表。

下面是一个使用List casteFrom进行浅层复制的例子。

void main() {
  List original = [1, 2, 3];
  var cloned = List.castFrom(original);

  original.add(5);
  original.remove(2);

  print(original); //[1, 3, 5]
  print(cloned); //[1, 3, 5]
}

深度复制列表

有多种方法来创建引用以及内存位置的精确拷贝。 在这里,对原始列表的改变不会在被拷贝的对象中得到改变。

  • 使用spread operator(...)

传播操作符在dart 2.3版本中引入。传播操作符传播数据,并通过传播数据赋值给一个新的变量。

这是一个使用传播操作符进行深度克隆的例子。

void main() {
  List original = [1, 2, 3];
  List cloned = [...original];
  original.add(5);
  print(original); //[1, 2, 3, 5]
  print(cloned);//[1, 2, 3]
}
  • 使用List addAll方法

在这个例子中,用空数组的addAll()方法将原始列表追加到克隆对象。

原始列表使用add和remove()方法进行添加和删除。然而,克隆对象并没有删除或添加新的元素。

这是一个使用List addAll方法进行深度克隆的例子。

void main() {
  List original = [1, 2, 3];
  List cloned = []..addAll(original);
  original.add(5);
  original.remove(2);

  print(original); //[1, 3, 5]
  print(cloned); //[1, 2, 3]
}

  • 使用List from方法

List 提供了一个使用 from()方法的命名构造函数,它接受一个动态类型的List。

这是一个使用List from方法进行深度复制的例子。

void main() {
  List original = [1, 2, 3];
  List cloned = List.from(original);
  original.add(5);
  original.remove(2);

  print(original); //[1, 3, 5]
  print(cloned); //[1, 2, 3]
}
  • List unmodifiable方法:使用immutable(List unmodifiable method)复制列表,这是一个使用List unmodifiable方法进行深度复制的例子。
void main() {
  List original = [1, 2, 3];
  var cloned = List.unmodifiable(original);
  original.add(5);
  original.remove(2);

  print(original); //[1, 3, 5]
  print(cloned); //[1, 2, 3]
}
  • List unmodifiable方法:List的方法提供了另一种方法,从现有的列表中创建一个列表的副本。

这是一个使用List of the方法进行深度拷贝的例子。

void main() {
  List original = [1, 2, 3];
  var cloned = List.of(original);

  original.add(5);
  original.remove(2);

  print(original); //[1, 3, 5]
  print(cloned); //[1, 2, 3]
}
  • 使用List toList方法:List toList方法创建一个原始列表的深度拷贝。

这是一个使用List toList方法进行深度拷贝的例子。

void main() {
  List original = [1, 2, 3];
  var cloned = original.toList();

  original.add(5);
  original.remove(2);

  print(original); //[1, 3, 5]
  print(cloned); //[1, 2, 3]
}
  • 使用List generate方法:另一种方法是使用List generate方法创建一个可增长的列表,它创建了两个对象和引用。这是一个使用List generate方法进行深度拷贝的示例代码。
void main() {
  List original = [1, 2, 3];
  var cloned = List.generate(original.length, (index) => original[index]);

  original.add(5);
  original.remove(2);

  print(original); //[1, 3, 5]
  print(cloned); //[1, 2, 3]
}
  • 使用List map方法:最后,使用stream map方法遍历一个原始列表,使用toList()方法将元素流转换成一个列表。

使用List map方法进行深度拷贝的示例代码。

void main() {
  List original = [1, 2, 3];
  List cloned = original.map((item)=>item).toList();

  original.add(5);
  original.remove(2);

  print(original); //[1, 3, 5]
  print(cloned); //[1, 2, 3]
}

总结

总结一下,学习了用浅层和深层克隆的方式来克隆或复制一个对象的多种方法,并举例说明