Help us understand the problem. What is going on with this article?

Dartにおけるリスト(配列)のインスタンス生成による違い

More than 5 years have passed since last update.

Dartではリスト(配列)としてList<E>クラスを用いますが、インスタンス生成の方法によって内部の実装クラスが変化し、挙動に影響します。具体的に言うと、インスタンス生成の時点で、そのリストが「可変長かどうか」でクラスが使い分けられ、可変長でないリストに対してadd()clear()などのリスト長が変化するメソッドを呼び出すとエラーとなります。

というわけでDartにおけるリストのインスタンス生成方法についてまとめました。なお今回の例ではジェネリクスは省略していますが、本来はつけるべきです。

空(長さ0, 可変長)のリスト

単純な可変長配列として使うならこの方法です。

var list = new List();

もしくは

var list = [];

出力結果

[]

空(長さ10, 可変長)のリスト

インデックスが存在するのではじめからlist[0]等のアクセスが可能になります

var list = []..length = 10;

もしくは

var list = new List.generate(10, (i)=>null);

出力結果

[null, null, null, null, null, null, null, null, null, null]

初期値あり(長さ10, 可変長)

任意の値を入れたいのであれば

var list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

インデックスにより導出できる値であれば

var list = new List.generate(10, (i)=> i);

出力結果

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

空(長さ10, 固定長)

一つ目の落とし穴がここです。他の言語(例えばJava)ではListのコンストラクタに初期長さを与えるとメモリ確保だけしてくれるような感じですが、Dartで同じことをすると思わぬエラーが出ます。

var list = new List(10);

初期値あり(長さ10, 固定長)

var list = new List.filled(10, 1);

出力結果

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

ここで2つ目の落とし穴です。List.filledList.generateと違い、遅延実行ではなく、与えられたオブジェクトをそのままリストの初期値にします。そのため、参照型のオブジェクトを与えればすべての要素が同一オブジェクトとなります。つまり次のようなことになります。

var list = new List<List>.filled(2, []);
for (var i = 0; i < 2; i++) {
  list[i].add(i);
}

出力結果

[[0, 1], [0, 1]]

ちなみに、やりたかったことはこうです。

var list = <List>[[], []];
for (var i = 0; i < 2; i++) {
  list[i].add(i);
}

出力結果

[[0], [1]]

まとめ

var list = new List(); // 長さ0, 可変長
var list = new List(10); // 長さ10, 固定長
var list = []; // 長さ0, 可変長
var list = []..length = 10; // 長さ10, 可変長
var list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // 長さ10, 可変長
var list = new List.generate(10, (i)=>i); // 長さ10, 可変長
var list = new List.filled(10, 0); // 長さ10, 固定長

ちなみにList.fromにはオプション引数にgrowableがあるので、これをfalseにすると固定長として生成することが出来ます。

lacolaco
I play Angular and pray for Angular. No Breaking Changes, No Life.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした