首页 > 代码库 > 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 使用可变数据结构