首页 > 代码库 > 11.1.2.1 使用可变数据结构
11.1.2.1 使用可变数据结构
11.1.2.1 使用可变数据结构
在清单11.4 中,可以看到两个函数,处理的集合保存了前面示例的地名。这一次,我们使用C#,把地名保存在标准的List<T> 类型中,它是可变的。
清单11.4 处理保存在List<T> 中的地名(C#)
List<string> LoadPlaces() { [1]
returnnew List<string> { "Seattle", "Prague",
"NewYork", "Grantchester", "Cambridge" };
}
void PrintLongest(List<string> names){ [2]
varlongest = names[0]; <-- 第一外地名
for(inti = 1; i < names.Count; i++)
if(names[i].Length > longest.Length) longest = names[i]; <-- 记住当前最长的名字
Console.WriteLine(longest);
}
void PrintMultiWord(List<string> names){ [3]
names.RemoveAll(s=> !s.Contains(" ")); <-- 删除只有一个字的名字
Console.WriteLine("Withspace: {0}", names.Count);
}
第一个函数加载样本数据[1],像前面的loadPlaces 函数一样,除了没有人口值;接下来,实现了两个处理函数,第一个函数[2]查找名字最长的地方,第二个函数[3]通过删除不包含空格的名字,确定包含多个单词地名的数量。尽管方法使用了lambda 函数的语法,但是,肯定不是函数式的:因为RemoveAll 方法修改了names 集合。如果我们要在后面的程序中使用这些函数,可以这样写代码:
PrintMultiWord(LoadPlaces()); // Prints‘1‘
PrintLongest(LoadPlaces()); // Prints ‘Grantchester‘
虽然得到了正确的结果,但是,两次调用LoadPlaces 函数,这似乎是不必要的。如果函数从数据库中加载数据,出于性能的原因,只一次检索数据会更好。可以进行简单的重构,只一次调用函数,把地名保存在局部变量中:
var places = LoadPlaces();
PrintMultiWord(places); // Prints ‘1‘
PrintLongest(places); // Prints ‘New York‘
简单的改变之后,我们没能得到正确的结果!如果仔细阅追踪源代码,可能已经发现问题了:List<T> 是可变数据结构,函数PrintMultiWord 在调用RemoveAll 时,意外地修改了它;当我们在代码的后面调用PrintLongest 时,集合places 中只包含了一项,即“NewYork”。现在,我们看看如果使用不可变数据结构,为什么就不会出现类似的错误。
11.1.2.1 使用可变数据结构