第一百二十五回 dart中List和Map的常见用法

本文介绍了Dart中的List和Map概念、初始化方法、相互转换以及元素操作,强调实践的重要性,并分享了使用经验和查找功能的建议。


我们在上一章回中介绍了Flexible组件相关的内容,本章回中将介绍 dart中的List和Map.闲话休提,让我们一起Talk Flutter吧。

概念介绍

我们在这里介绍的List也叫列表,它表示一组相同类型变量的集合。map也叫映射或者字典,它表示键值对的组合。在高级语言中都有list和map,比如Java,Swift以及Kotlin,dart也提供list,本章回中将是介绍它们的用法。为什么要在这里介绍?因为在前面章回中介绍的各种单选列表,复选列表都需要使用List,而我们在前面章回中没有介绍过List相关的知识,很多看官们希望我们介绍List相关的知识,因此才有了本章回的内容。

使用方法

初始化

List初始化可以使用中括号,在中括号内输入具体数值相当于给List赋值。还可以使用generate()方法来初始化List.

map的初始化使用大括号,在大括号内输入数值,相关于给map赋值,还可以通过List转换成map来给map赋值。下面是示例代码:

    List<int> intList = List.generate(3, (index) => index+2);
    List<String> strList = ['one','two','three','four','five'];
    Map<int,int> iMap = {1:1,2:2}; 
    Map<int,int> intMap = intList.asMap();

相互转换

List和map可以相互转换,List转换成map时索引值从0开始,与索引值对应的value就是list中的元素的值,比如:map[key,value],list= [value...] key=index...,value=list[index];.map中的key和value可以单独转换成List.下面是示例代码:

    Map<int,int> intMap = intList.asMap();
    Map<int,String> strMap = strList.asMap();
    ///map的key和value可以单独转换成list
    List<int> exchangeIntList = intMap.values.toList();
    List<int> exchangeIntListKey = intMap.keys.toList();

元素操作

List中的元素可以通过map()方法对元素进行相关操作,然后把操作后的内容再转换成List.这个功能在程序中经常使用,下面是示例代码:

    ///把List中的每个元素都加3后生成新的List
    List<int> filterList = intList.map((e) => e+3).toList();
    ///把String类型的List转换成ListTile类型的List
    strList.map((e) => ListTile(title: Text(e)),).toList();

经验分享

上面介绍的这些内容是我们在博客中经常使用的内容,建议大家自己动手去实践一下,这样才能掌握List和map的使用方法。List和map是常用的类型,它们还有很多的用法,我在这里就不详细介绍了。我的经验是:如果想使用某个功能,先看看没有现成方法,然后再查看该方法的源代码,源代码中包含有详细的说明和示例程序。依据示例程序就可以实现我们想要的功能。

看官们,与list和map相关的内容就介绍到这里,欢迎大家在评论区交流与讨论!

<think>我们正在讨论的是Dart中函数参数传递的问题,特别是当参数是ListMap这样的集合类型时。在Dart中,所有的参数传递都是按值传递,但这个值对于对象(包括ListMap自定义对象)来说,实际上是对象的引用(也就是内存地址)。因此,在函数内部修改参数(如添加、删除元素)会影响到原始数据。 但是,这里有一个重要的区别: 1. 如果你修改的是引用所指向的对象的内容(例如,修改List的某个元素,或者向List中添加元素,修改Map的键值对等),那么原始对象会被修改。 2. 如果你修改的是参数变量本身(即让参数变量指向一个新的对象),那么原始对象不会受到影响。 下面我们通过示例来说明。 示例1:修改List的内容(会影响原始数据) ```dart void modifyList(List<int> list) { list[0] = 100; // 修改列表的第一个元素 list.add(4); // 向列表添加一个元素 } void main() { List<int> originalList = [1, 2, 3]; modifyList(originalList); print(originalList); // 输出: [100, 2, 3, 4] 原始数据被修改 } ``` 示例2:重新赋值List参数(不会影响原始数据) ```dart void reassignList(List<int> list) { list = [10, 20, 30]; // 这里只是将局部变量list指向了一个新的列表 // 但原始列表并没有改变 } void main() { List<int> originalList = [1, 2, 3]; reassignList(originalList); print(originalList); // 输出: [1, 2, 3] 原始数据未被修改 } ``` 对于Map也是同样的道理: 示例3:修改Map的内容(会影响原始数据) ```dart void modifyMap(Map<String, int> map) { map['a'] = 100; // 修改键'a'对应的值 map['c'] = 3; // 添加新的键值对 } void main() { Map<String, int> originalMap = {'a': 1, 'b': 2}; modifyMap(originalMap); print(originalMap); // 输出: {a: 100, b: 2, c: 3} 原始数据被修改 } ``` 示例4:重新赋值Map参数(不会影响原始数据) ```dart void reassignMap(Map<String, int> map) { map = {'x': 10, 'y': 20}; // 局部变量map指向了新的Map } void main() { Map<String, int> originalMap = {'a': 1, 'b': 2}; reassignMap(originalMap); print(originalMap); // 输出: {a: 1, b: 2} 原始数据未被修改 } ``` 因此,如果你在函数中修改了ListMap参数的内容(而不是重新赋值),那么原始数据会被修改。如果不希望原始数据被修改,可以在函数内部使用深拷贝(如之前讨论的深拷贝方法)来创建一个副本,然后操作这个副本。 例如,为了避免函数修改原始List,我们可以这样做: ```dart void modifyListWithoutAffectingOriginal(List<int> list) { // 创建深拷贝(对于元素是基本类型ListList.from或[...]即可) List<int> copy = List<int>.from(list); copy[0] = 100; copy.add(4); // 此时原始list不变 } void main() { List<int> originalList = [1, 2, 3]; modifyListWithoutAffectingOriginal(originalList); print(originalList); // 输出: [1, 2, 3] } ``` 注意:如果ListMap中嵌套了其他对象(非基本类型),那么浅拷贝(如List.from、[...]或Map.from)只能拷贝第一层,内层的对象仍然是引用。这时就需要深拷贝,如使用`json.decode(json.encode(...))`或递归拷贝。 总结: - 在Dart中,函数参数传递是传递引用的拷贝(即按值传递引用)。 - 在函数内修改参数的内容(如List的元素)会影响到原始数据。 - 在函数内重新赋值参数变量(即让参数变量指向新的对象)不会影响原始数据。 - 如果需要保护原始数据不被修改,应该在函数内部使用深拷贝操作副本。 引用说明: 在引用[1]中提到了List的创建修改,引用[2]中提到了Map的修改。这些操作在函数内部同样适用,并且会改变原始数据。 相关问题: 1. Dart中如何实现深拷贝以保护原始数据不被函数修改? 2.Dart中,如何判断两个变量是否指向同一个对象? 3.Flutter状态管理中,为什么有时需要深拷贝来更新状态? 4. Dart中的基本类型(如int, double, bool)对象类型在函数参数传递时行为有何不同?</think>在 Dart 中,**修改函数内的 ListMap 参数会直接影响原始数据**,因为 Dart 传递的是对象的引用(内存地址),而非值的副本。这基本类型(如 int、bool)的行为不同,基本类型在函数参数传递时是值传递。 ### 示例说明 #### 1. List 参数修改影响原始数据 ```dart void modifyList(List<int> list) { list[0] = 100; // 修改第一个元素 list.add(4); // 添加新元素 } void main() { List<int> original = [1, 2, 3]; modifyList(original); print(original); // 输出: [100, 2, 3, 4](原始数据被修改) } ``` - **原因**:`original` 函数参数 `list` 指向内存中的同一个数组对象[^1]。 #### 2. Map 参数修改影响原始数据 ```dart void modifyMap(Map<String, int> map) { map['b'] = 200; // 修改键值 map['d'] = 4; // 添加新键值 } void main() { Map<String, int> original = {'a': 1, 'b': 2, 'c': 3}; modifyMap(original); print(original); // 输出: {a: 1, b: 200, c: 3, d: 4}(原始数据被修改) } ``` - **原因**:函数内的 `map` 参数 `original` 引用同一个 Map 对象[^2]。 --- ### 避免副作用的解决方案 #### 方案 1:创建副本再传递 ```dart void safeModifyList(List<int> list) { List<int> copy = List.from(list); // 创建新副本 copy[0] = 100; copy.add(4); } void main() { List<int> original = [1, 2, 3]; safeModifyList(original); // 传递副本 print(original); // 输出: [1, 2, 3](原始数据不变) } ``` #### 方案 2:深拷贝嵌套结构 ```dart // 深拷贝工具函数 List<T> deepCopyList<T>(List<dynamic> list) { return list.map((e) { if (e is List) return deepCopyList(e); // 递归嵌套列表 if (e is Map) return deepCopyMap(e); // 递归嵌套Map return e; // 基本类型直接返 }).toList(); } void main() { List<dynamic> original = [1, [2, 3], {'a': 4}]; List<dynamic> copy = deepCopyList(original); copy[1][0] = 99; // 修改嵌套列表 copy[2]['a'] = 100; // 修改嵌套Map print(original[1]); // 输出: [2, 3](未改变) print(original[2]); // 输出: {a: 4}(未改变) } ``` --- ### 关键概念总结 | **操作** | 基本类型 (int/bool) | List/Map/自定义对象 | |------------------------|---------------------|---------------------| | **函数内修改值** | ❌ 不影响原始数据 | ✅ 影响原始数据 | | **传递方式** | 值传递 (复制值) | 引用传递 (复制地址) | | **安全修改方法** | 无需特殊处理 | 需创建深拷贝 | --- ### 何时需要深拷贝? 1. **跨函数数据隔离**:当函数需要修改集合但不应影响原始数据时 2. **状态管理**:在 Flutter 中更新状态对象(如 Provider/Riverpod) 3. **嵌套结构修改**:当集合包含其他集合或自定义对象时 4. **并发操作**:多线程环境(Isolate)中避免共享可变状态 > **注意**:对于简单结构(仅含基本类型),`List.from()` `Map.from()` 已足够。嵌套结构需递归深拷贝。 --- ### 相关问题 1. Dart 中如何判断两个变量是否引用同一对象?`identical()` 函数的使用场景是什么? 2.Flutter 状态管理中,为什么 `setState()` 要求创建新对象而非直接修改状态? 3. Dart 的 `freezed` 包如何通过代码生成实现不可变对象自动深拷贝? 4. 如何为包含循环引用的 Dart 对象(如双向链表)实现深拷贝?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

talk_8

真诚赞赏,手有余香

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值