Dart/Flutter – How to clone/copy a list

Note: in this post, I share the way we clone/copy a list of immutable elements, it’s called shallow copy. That means if your elements are mutable and you try to change the element properties, it will affect both lists (original list and copied list). I will have another post to demonstrate how to create a deep copy list later, or you can scroll down to the comment session and find my solution there.

In this post, we will learn how to clone/copy an original list to a new list. But before that, let’s look at the below example to understand why we need to clone/copy, instead of using the original list.

void testAssignList() {
  print('Test assign list');
  var numbers = [1, 2, 3];
  var newNumbers = numbers;
  // Print the first element of new list
  print(newNumbers[0]);

  // Change original list 
  numbers[0] = 100;
  // Try to print the first element of new list again
  print(newNumbers[0]);
}
Test assign list
1
100


As you see, when we change the value of the original list (numbers – line 9), the value of the new list (newNumbers) is updated too. The reason is when we assign (using “=”), new list (newNumbers) will “refer” or “point” to the same memory of the original list (numbers). In other words, number and newNumbers are just 2 names of the same list. Changing on either list will affect the other one.

The same problem happens if we use another kind of assigned operator, like the static method castFrom()

var newNumbers = List.castFrom(numbers);


👇👇👇

In many cases, we will need to keep the original list and work on the cloned version of it. That is when we have to clone/copy, instead of assign. Dart provides some factory constructors to satisfy this requirement:

var newNumbers = List.from(numbers);
var newNumbers = List.generate(numbers.length, (index) => numbers[index]);
var newNumbers = List.of(numbers);
var newNumbers = List.unmodifiable(numbers);

All the code

void main() {
  testAssignList();

  testCreateListUsingCastFromMethod();

  print('* * * * * * * * * * ');

  testCreateListUsingFromMethod();

  testCreateListUsingGenerateMethod();

  testCreateListUsingOfMethod();

  testCreateListUsingUnmodifiableMethod();
}

void testAssignList() {
  print('Test assign list');
  var numbers = [1, 2, 3];
  var newNumbers = numbers;
  // Print value of new list
  print(newNumbers[0]);

  // Change original list
  numbers[0] = 100;
  // Try to print the value of new list again
  print(newNumbers[0]);
}

void testCreateListUsingCastFromMethod() {
  print('Create list using List.castFrom() method');
  var numbers = [1, 2, 3];
  var newNumbers = List.castFrom(numbers);
  print(newNumbers[0]);

  numbers[0] = 100;
  print(newNumbers[0]);
}

void testCreateListUsingFromMethod() {
  print('Create list using List.from() method');
  var numbers = [1, 2, 3];
  var newNumbers = List.from(numbers);
  print(newNumbers[0]);

  numbers[0] = 100;
  print(newNumbers[0]);
}

void testCreateListUsingGenerateMethod() {
  print('Create list using List.generate() method');
  var numbers = [1, 2, 3];
  var newNumbers = List.generate(numbers.length, (index) => numbers[index]);
  print(newNumbers[0]);

  numbers[0] = 100;
  print(newNumbers[0]);
}

void testCreateListUsingOfMethod() {
  print('Create list using List.of() method');
  var numbers = [1, 2, 3];
  var newNumbers = List.of(numbers);
  print(newNumbers[0]);

  numbers[0] = 100;
  print(newNumbers[0]);
}

void testCreateListUsingUnmodifiableMethod() {
  print('Create list using List.unmodifiable() method');
  var numbers = [1, 2, 3];
  var newNumbers = List.unmodifiable(numbers);
  print(newNumbers[0]);

  numbers[0] = 100;
  print(newNumbers[0]);
}
Test assign list
1
100
Create list using List.castFrom() method
1
100
* * * * * * * * * * 
Create list using List.from() method
1
1
Create list using List.generate() method
1
1
Create list using List.of() method
1
1
Create list using List.unmodifiable() method
1
1

Hope this post is useful for you! 
If you are looking for a developer or a team to build your next projects, please Drop us your request!

Tagged : / / / / /
Subscribe
Notify of
guest
14 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
Jalal
Jalal
2 months ago

I also did all ways but I get same result

Phuc
Phuc
Reply to  Jalal
2 months ago

Can you share your code?

Jalal
Jalal
Reply to  Jalal
2 months ago
class CategoryModel {
  int? id;
  bool? title;
  List<CategoryValueModel>? values;
  List<CategoryDifinitionModel>? children;

  CategoryModel(
      {this.id,
        this.title,
        this.values,
        this.children,
        });

}

class CategoryValueModel {
  int? id;
  String? value;
  String? uri;

  CategoryDifinitionValueModel(
      {this.id, this.value, this.uri});

}

List<CategoryDifinitionModel> itemsList = [];
// then i fill 'itemsList' from json api
print(items[0].values.length);
//.... will be 5 for example
// then
List<CategoryModel> testList = []..addAll(itemsList);
testList[0].values = [];
print(itemsList[0].values.length);
//.... will be 0 



Last edited 2 months ago by Jalal
Jalal
Jalal
Reply to  Jalal
2 months ago

When I update the ‘values list’ or any thing from the second list
I find the source list is updated.

Jalal
Jalal
Reply to  Jalal
2 months ago

yes… but in Flutter no. So, I found a way to convert a source list to a JSON object, then I make a new list from a JSON object, That’s work for me.

Mahdi
Mahdi
7 months ago

thanks so much

Danny
Danny
11 months ago

Good tutorial. Thank you!

Aboud
Aboud
11 months ago

i did all ways but i get sameresult , when chang something in new array it change in old array too..(in Flutter app)–

arrayBackup = List.unmodifiable(array);
arrayBackup = List.from(array);
arrayBackup = List.of(array);
but in dartpad everything is ok !!!!!!!!!but in Flutter is Noway.
Jalal
Jalal
Reply to  Aboud
2 months ago

I also did all ways but I get same result

14
0
Would love your thoughts, please comment.x
()
x