如何在C#中使用LINQ?结合ConcurrentDictionary与文件读取场景
嘿,我来帮你把这段文件读取和单词统计的代码用LINQ优化得更简洁优雅!先理清楚你的核心需求:读取指定索引的文件,逐行转小写、按空格分割单词,最终把单词出现次数统计到ConcurrentDictionary<string, int>里对吧?
用LINQ优化的核心实现
我们可以利用LINQ的链式调用结合.NET内置的文件读取方法,把原来的循环逻辑简化成更易读、更安全的代码:
int i = (int)obj; string targetFile = file[i]; // 一步完成读取、转换、分割、统计并生成线程安全字典 var wordCounts = new ConcurrentDictionary<string, int>( File.ReadLines(targetFile) // 逐行转小写,和原逻辑保持一致 .Select(line => line.ToLower()) // 按空格分割单词,自动过滤空字符串(比如连续空格、行首尾空格) .SelectMany(line => line.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries)) // 按单词分组统计出现次数 .GroupBy(word => word) // 把分组结果转换成键值对(单词-次数) .Select(group => new KeyValuePair<string, int>(group.Key, group.Count())) );
为什么这比原来的代码更好?
- 自动资源管理:
File.ReadLines会自动处理文件流的打开和关闭,不用手动写using或者try/finally释放StreamReader,避免了资源泄漏的风险。 - 代码可读性拉满:链式调用清晰表达了「读取行→转小写→分割单词→分组统计→生成线程安全字典」的完整逻辑,比嵌套的
while循环更容易理解和维护。 - 避免无效数据:通过
StringSplitOptions.RemoveEmptyEntries自动过滤分割产生的空字符串,不用额外写判断逻辑。 - 统计效率更高:
GroupBy在内存中一次性完成统计,比逐行更新ConcurrentDictionary减少了锁竞争,尤其当单词重复率高的时候性能提升明显。
超大型文件的备选方案
如果你的文件特别大,不想把所有分组数据都放在内存里,可以用Aggregate逐行更新字典,内存占用更低:
var wordCounts = File.ReadLines(targetFile) .Select(line => line.ToLower()) .SelectMany(line => line.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries)) .Aggregate(new ConcurrentDictionary<string, int>(), (dict, word) => { // 自动处理新增/更新逻辑:不存在则设为1,存在则次数+1 dict.AddOrUpdate(word, 1, (_, currentCount) => currentCount + 1); return dict; });
这种方式适合超大规模文件,但因为每次操作都要触发ConcurrentDictionary的线程安全检查,性能会比GroupBy稍差一点,你可以根据实际场景选择。
内容的提问来源于stack exchange,提问作者Jhon
相关产品推荐
相关产品推荐

