Dart コレクション

一、Dart 標準搭載の3種コレクション

Dart 言語には標準で3種類のコレクションが用意されています:ListSetMap

コレクション内の要素の型制限はジェネリクス(Generics)で設定できます。

コレクション型主な特徴リテラル記号
List順序あり、重複許可、添字アクセス可能[]
Set順序不定、要素重複不可、添字なし{}(ジェネリクスを明示しないとMapと判定される)
Mapキー・値ペアで保存、Keyは一意、Valueは重複可{key: value}

二、List リスト(順序付き配列)

1. 基本定義と型推論

  • Dart における配列は本質的に List オブジェクトで、リテラル [] で作成;
  • 型が自動推論されます。例:var list = [1,2,3]List<int>、int以外の値を挿入するとエラー;
  • 末尾カンマに対応、文法上問題なくコピー貼り付け時のミスを減らせます:var list = ['Car', 'Boat', 'Plane',];

2. 基本操作

  1. 添字ルール:0 から開始、list.length - 1 が最後の添字;
  2. 要素の取得/更新:list[index]list[index] = 新しい値
  3. 要素数の取得:.length プロパティ;

サンプル

void main() {
	var list = [1,2,3];
	print(list.length);//要素数 3 を出力
	print(list[1]);// 2 を出力
	list[1] = 9; //2番目の要素を9に変更
	print(list[1]);//変更後の値 9 を出力
}Code language: Dart (dart)

3. 定数リスト(コンパイル時不変)

リテラルの前に const を付けると、実行時に要素の追加・削除・変更ができなくなります:

void main() {
	var constantList = const [1,2,3];
	constantList[1] = 100; // コンパイルエラー
}Code language: Dart (dart)
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Unhandled exception:
Unsupported operation: Cannot modify an unmodifiable list
#0      UnmodifiableListMixin.[]= (dart:_internal/list.dart:89:5)
#1      main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:4:14)
#2      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#3      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)

三、Set セット

順序不定、要素が一意のコレクション

1. Set の核心特徴

  • 順序不定:要素に固定の添字が存在せず、[添字] で値の取得・変更は不可
  • 要素の一意性:自動的に重複を削除、重複要素を追加してもエラーにはならず1つだけ保持
  • リテラル記号:波括弧 {}
  • ジェネリクス制約:単一の型のみ格納するよう制限可能、異なる型を挿入するとコンパイル/実行時エラー

空のSetと空のMapの区別(初心者がミスしやすい点)

{} は既定で Map と判定されるため、空の Set を作成する場合はジェネリクスを明示する必要があります

void main() {
	// 空の Set<String>
	var names = <String>{};
	Set<String> names2 = {}; // 上記と等価な記述

	// ジェネリクスを記載しないと、Dart は Map<dynamic, dynamic> と判断
	var names3 = {};
}Code language: Dart (dart)
型推論
void main() {
	// Set<String> と自動推論
	var halogens = {'dog', 'cat', 'horse'};

	// Set<int> と自動推論
	var nums = {1, 2, 6, 2}; // 重複する2は自動削除、最終的に {1,2,6}

	// 型混在の場合 Set<Object> に推論(推奨しない、型チェックが無効化される)
	var mix = {1, "apple"};
}Code language: JavaScript (javascript)

型推論後、異なる型の要素を追加するとエラーが発生します

void main() {
  // リテラルが全文字列なので Set<String> と推論
  var animals = {'dog'};
  print(animals.runtimeType); // _CompactLinkedHashSet<String>

  // 同じ文字列型は正常に追加可能
  animals.add('cat');
  animals.add('pig');
  print(animals); // {dog, cat, pig}
  
  // エラー:addメソッドはString型を受け取るのにintを渡している
  animals.add(1); 
}Code language: Dart (dart)

2. 要素追加・削除と要素数

  • 単一要素追加:.add()
  • 一括追加:.addAll()
  • 要素総数取得:.length
var elements = <String>{};
elements.add('fluorine');
elements.addAll({'chlorine', 'bromine'});
print(elements.length); //3Code language: PHP (php)

3. 定数 Set

リテラル先頭に const を付けると、要素の追加/削除が禁止されます:

final constantSet = const {'fluorine', 'chlorine'};
// constantSet.add('helium'); // エラー発生Code language: PHP (php)

四、Map マップ(キー・値ペア)

1. 基本特徴
  • Key-Value のペアデータを格納;
  • Key は全体で一意、Value は重複可能;
  • Key、Value に任意のオブジェクト型を使用可能;
  • リテラル書式 {key: value}
  • 自動型推論機能:
void main() {
	var gifts = {'first': 'partridge'}; // Map<String, String> と自動推論
	
	var nobleGases = {2: 'helium'}; // Map<int, String> と自動推論
}Code language: Dart (dart)
2. 2種類の作成方法
  • リテラルによる作成
var gifts = {'first': 'partridge'};  Code language: Dart (dart)
  • Map コンストラクタによる作成(new キーワードは省略可)
// コンストラクタ記法
var gifts = Map<String, String>();
gifts['first'] = 'partridge';Code language: JavaScript (javascript)
3. 追加・取得・要素数
  1. キー値の新規追加/上書き:map[key] = value
  2. Keyから値を取得:map[key];Keyが存在しない場合は null を返却;
  3. キー値ペア総数取得:.length
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds'; // 新規追加
print(gifts['first']); //値を取得
print(gifts['fifth']);//存在しないKey取得
print(gifts.length); //ペア数を取得 Code language: PHP (php)
4. 定数 Map

リテラル先頭に const を付けると、キー値ペアの変更が禁止されます:

final constantMap = const {2: 'helium', 10: 'neon'};
// constantMap[2] = 'Helium'; // エラー発生Code language: Dart (dart)

五、コレクションリテラル拡張構文

コレクションリテラル内部で各種特殊構文を利用可能。大きく基本要素制御フロー要素の2種類に分かれ、コレクション生成コードを簡略化できます。

  1. 基本要素:単一式、Mapキー値、Null安全要素
  2. 制御フロー要素:展開演算子、if条件、forループ、入れ子組み合わせ

1. 通常式要素

最も基礎的な記法。式を直接記述し、計算結果がコレクションに挿入されます。下記例の2番目の要素は 2 * 3 の計算結果となり、出力は [1, 6, text] です

void main() {
	var list = [1, 2 * 3, 'text'];
	print(list); //[1, 6, text]
}Code language: PHP (php)

2. キー値要素

Mapリテラル専用、キー式 : 値式 の書式。下記例では1番目のキーと値が両方式から算出されています。

void main() {
	var map = {1+1: 3*8, 'name': 'apple'};
	print(map); //{2: 24, name: apple}
}Code language: Dart (dart)

3. Null安全要素(Dart ≥3.8)

構文 ?式:式の結果がnullでない場合のみコレクションに挿入、nullの場合は無視されます

Listで使用例:aがnullのため最終的に挿入されず、エラーなし

int? a = null;
int? b = 3;
var items = [1, ?a, ?b, 5]; // [1, 3, 5]Code language: JavaScript (javascript)

Mapで使用(key/valueどちらにも?を付けられる)

String? k = null;
int? v = null;
var m = {?k: ?v}; // keyまたはvalueのどちらかがnullの場合、キー値ペア全体が破棄される
Code language: JavaScript (javascript)

4. Spread element 展開演算子

① 通常展開 ...

反復可能なコレクションの全要素を展開して挿入。nullのコレクションを展開するとエラー

var a = [1,2,3];
var items = [0, ...a, 4]; // [0,1,2,3,4]Code language: JavaScript (javascript)
② Null安全展開 ...?

null許容コレクション対応:コレクションがnullの場合無視、エラーなし;

コレクション自体はnullでなくても内部にnull要素が含まれる場合、nullは保持されます

List<int>? a = null;
var b = [1, null, 3];
var items = [0, ...?a, ...?b, 4]; // [0, 1, null, 3, 4]Code language: PHP (php)

規約:nullを許可するコレクションには必ず ...? を使用しないとコンパイルエラーとなります。

5. If element 条件要素

コレクション内に直接if分岐を記述可能。条件成立時のみ要素を挿入。真偽判定、if-caseパターンマッチ、elseに対応

基本真偽判定
void main() {
	bool flag = true;
    var list = [0, if(flag) 1 else 99, 2];
	print(list); //[0, 1, 2]
}Code language: Dart (dart)
if-case パターンマッチ(型・配列分解)
void main() {
	Object data = 123;
	var info = [
	  if(data case int i) '数値:$i',
	  if(data case String s) 'テキスト:$s'
	];
	print(info); //[数値:123]
}Code language: Dart (dart)

dataがint型のため「数値:123」だけ挿入され、テキスト側は無視されます

6. For element ループ要素

コレクション内にforループを直接記述し、ループで複数要素を生成。for-in / 従来の3項forに対応

var nums = [2,3,4];

// for-in
var list1 = [1, for(var n in nums) n*n, 7]; // [1,4,9,16,7]

// 3項形式for
var list2 = [1, for(var x=5; x>2; x--) x, 7]; // [1,5,4,3,7]Code language: JavaScript (javascript)

7. 入れ子制御フロー

if、for、展開演算子は任意に多段階入れ子可能。他言語のリスト内包表記と同等の役割

サンプル:偶数のみ抽出

var numbers = [1,2,3,4,5,6];
var items = [
  0,
  for(var n in numbers)
    if(n.isEven) n,
  8
]; // [0,2,4,6,8]Code language: JavaScript (javascript)

例:入れ子 for + if + 展開演算子

void main() {
	var ys = [1,2,3];
	var nest = [
	  ...[
		for(var x=0;x<2;x++)
		  for(var y in ys)
			if(x<y) x+y*10
	  ]
	];
	print(nest); //[10, 20, 30, 21, 31]
}Code language: Dart (dart)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です