第十四章 支持标准查询操作符的集合接口
来源:互联网 发布:怎么更换淘宝的实名制 编辑:程序博客网 时间:2024/06/05 09:23
1、集合接口
1.1 IEnumerator和IEnumerable
1.2.1 IEnumerator接口
IEnumerator接口定义了遍历集合的基本方法,MoveNext()方法从集合的一个元素移动到下一个元素,如果越过集合末尾则返回false。Current是只读成员,用于返回当前元素。Reset()方法一般会抛出异常,所以一般不会调用。
public Interface IEnumerator
{
bool MoveNext();
object Current {get;}
void Reset();
}
1.2.2 IEnumerable接口
IEnumerable接口只有一个GetEnumerator()方法,用于获取枚举器。集合类不直接支持IEnumerator接口,而是支持IEnumerable接口。通过GetEnumerator获取枚举器,然后由其他类维持游标状态。
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
IEnumerable接口的作用:
- 支持foreach语句;
- 支持集合初始化;
- 作为一个标准的集合类与其他类库进行交互
1.3 ICollection<T>和ICollection
ICollection直接继承IEnumerable。ICollection除了具备IEnumerable的遍历集合的功能外,还增加维护集合的功能:
- 统计集合的元素个数;
- 获取元素下标;
- 判断元素是否存在;
- 添加、移除元素。
ICollection<T>和ICollection略有不同,ICollection不提供编辑集合的功能,即Add、Remove以及检查元素是否存在。
1.4 IList<T>和IList
IList直接继承ICollection和IEnumerable,IList除了包括两者的功能外,还支持了根据下标访问和处理元素的功能,如,IndexOf、Insert、RemoveAt等。
1.5 IReadOnlyList<T>
IReadOnlyList是.Net4.5中新增的接口,可以看作IList<T>的缩减版,该接口去掉了所有可能修改集合的功能。
1.6 IDictionary<TKey, TValue>
IDictionary继承自ICollection<T>和IEnumerable。IDictionary提供了键值对访问集合的功能,扩展了通过Key值操作数据的方法。
2、标准查询操作符
IEnumerable<T>上每个方法都是一个标准查询操作符,用于为所操作的集合提供查询功能。
IEnumerable<T>除了提供GetEnumerator()方法外,还提供了多个标准查询方法,这些方法由扩展类System.Linq.Enumerable类提供,所以若要使用这些扩展方法需要引用System.Linq。
2.1 Where()筛选
Where()方法中可以传递一个Lambda表达式或Lambda语句,根据Lambda表达式的筛选条件返回一个新的集合。
实例:筛选出集合中每个属性YearOfPublication由"18"开头上午对象。
IEnumerable<Patent> patents = PatentData.Patents;
patents = patents.Where(p => p.YearOfPublication.StartsWith("18"));
注意: Where() 方法的表达式实参并非一定是在赋值时求值的,只有在需要遍历集合项时,才会对表达式求值。
2.2 Select()投射
Select()与Where()类似,可以按照元素所在位置判断处理,而Select()所指定的处理式Selector必须返回一个对象,该对象可以是指定类型,也可以是匿名类型。
实例:根据筛选后的结果返回新的对象
IEnumerable<Patent> patents = PatentData.Patents;
patents = patents.Where(p => p.YearOfPublication.StartsWith("18")).Select(p => new Patent {Title = p.Title, YearOfPublication = p.YearOfPublication, InventorIds = p.InventorIds});
2.3 Count()计数
Count()的作用是统计元素个数,如果集合提供Count属性,则首选是使用Count属性。ICollection<T>有Count属性,而IEnumerable<T>会枚举整个集合
Console.WriteLine("Count={0}", patents.Count(p => p.YearOfPublication.StartsWith("18")));
注意:如果只是要判断集合元素个数是否大于0,可以使用Any()方法,Any()遍历到集合中的第一个元素就返回,而Count()遍历所有元素。
2.4 OrderBy()和ThenBy()排序
OrderBy()根据传入的Lambda表达式提供的参数对集合进行排序,OrderBy()只会获取第一个参数来排序,如果增加第二个或更多排序因素,则要使用ThenBy()。
OrderBy()返回的是IOrderedEnumerable<T>接口,该接口继承自IEnumerable<T>接口,ThenBy()是IOrderedEnumerable<T>接口的扩展方法。
OrderByDescending()和ThenByDescending()提供相同的功能,只是变成了按降序排序。
实例:对集合进行排序,首先是按YearOfPublication排序,再按Title排序
IEnumerable<Patent> patents = PatentData.Patents;
patents = patents.OrderBy(p => p.YearOfPublication).ThenBy(p => p.Title);
注意:当访问集合成员时才开始排序。调用OrderBy()在调用ThenBy()会导致前面的OrderBy()再次被调用。
2.5 Join()内部联接
Join()的作用是根据一定条件将两个集合的成员联接成一个新的成员。Join()有四个参数,第一个参数是要联接的集合,第二和第三个参数是Lambda表达式,分别是两个集合联接的键值,第四个参数是也是Lambda表达式,用于返回新成员。
var items = employees.Join(
departments,
emp=>emp.departmentId,
dep=>dep.Id,
(emp, dep) => new
{
emp.id,
emp.name,
emp.title,
Department = dep
});
2.6 GroupBy()分组
GroupBy()的作用是根据Lamdba表达式对集合进行分组,返回IGrouping<TKey, TElement>类型。
IEnumerable<IGrouping<int, Employee>> groupEmployees = employees.GroupBy(emp => emp.DepartmentId);
2.7 推迟执行——查询的重复执行
这是Linq一个重要的特性,Lamdba表达式除非被调用,否则其中的代码不会被执行,由于这个特性,在一些意想不到的地方还是对整个集合进行了遍历。
static void Main(string[] args)
{
int[] scores = new int[] { 97, 92, 79, 60 };
bool result = false;
IEnumerable<int> scoreQuery = scores.Where(
score =>
{
result = false;
if (score > 80)
{
result = true;
Console.WriteLine("Score = {0}", score);
}
return result;
});
Console.WriteLine("1) Invoke empty foreeach, it will execute");
foreach (int i in scoreQuery)
{
}
Console.WriteLine("2) Invoke IEnumerable Count, it will execute");
scoreQuery.Count();
Console.WriteLine("3) Invoke IEnumerable ToArray, it will execute");
scoreQuery = scoreQuery.ToArray();
Console.ReadKey();
}
输出结果:
1) Invoke empty foreeach, it will execute
Score = 97
Score = 92
2) Invoke IEnumerable Count, it will execute
Score = 97
Score = 92
3) Invoke IEnumerable ToArray, it will execute
Score = 97
Score = 92
注意,Console.WriteLine("1) Invoke ... ..")是先于Lamdba表达式执行的,因为在这之前并未调用Lamdba表达式,这就是延迟执行的概念。
以下是会触发遍历集合的情况:
- foreach:foreach 的本质是调用 MoveNext(),这是会触发遍历的开关。
- Count:在前面讨论过,IEnumerable<T>的Count并不是一个属性,而是一个函数。
- ToArray等:ToXXX是个好东西,可以把集合变成可以安全操作的对象,但它同样会触发遍历,而且会把结果都加载到内存中。
- 第十四章 支持标准查询操作符的集合接口
- (13)支持标准查询运算符的集合接口
- 19.C#:支持标准查询运算符的集合接口,Linq查询语句
- 16 C# 第十四章 标准查询运算符
- LINQ 的标准查询操作符
- LINQ 的标准查询操作符
- LINQ定义的标准查询操作符
- LINQ 的标准查询操作符
- LINQ标准查询操作符
- LINQ标准查询操作符
- LINQ标准查询操作符
- 第十四章 python标准库
- 第十四章——转换操作符
- 第十四章:重载操作符与转换
- 第十四章 重载操作符与转换
- 第十四章 重载操作符与转换
- java集合框架集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。
- LINQ标准查询操作符详解
- 第十三章 事件
- NewsFragment
- Java后端工程师学习大纲
- 2017百度校招笔试第一题
- 如果小米系列手机调试报这个错误:Installation failed with message Failed to establish session
- 第十四章 支持标准查询操作符的集合接口
- 自动无限轮播
- AngularJS的$interval服务获取系统时间
- Python 复制移动文件
- ubuntu 文本编辑
- JS 封装实现根据开始时间算出当前第几周
- MyApplication
- Spring MVC+Maven 上传文件
- shape绘制方法