C# 泛型集合类List<T>使用总结
作者:握风 发布时间:2021-08-30 02:04:01
C#中List可谓是使用最广泛的一种数据类型了,使用他来规范数据时,往往会涉及到对数据的处理操作,相关处理数据方法也非常丰富,本文将简单介绍为何使用它,以及部分处理方法的灵活使用。
为什么选择使用List,而不是使用Array,或者ArryList
首先要说下数组的局限性
(1) 数组中元素是固定的:类型和数量都必须确定!一旦定义,无法改变其元素总数
(2) 如果使用数组类型存储数据,一旦项目需求有变化,那必须修改原数组相关代码,得不偿失
(3) 如果数据总数非常大,那数组在定义时就要把长度(即元素总数)定义的非常大,造成了存储空间的巨大浪费!
而List跟数组比较,他可以动态增减元素个数,无任何限制,直接秒杀数组
当然,实际项目开发中,对于一些固定的枚举值,类型集合等,或相关数据处理中,使用数组还是相当方便的,它并不是没用的,而是相比较List,使用的空间小一些罢了(存在即有用!)
然后再说下ArryList
这个直接截图一下官网的相关建议
既然官网都不建议使用,那可见它真的不常用,而不是不能用
没有使用价值的东西不会被留下来的,对吧!
跟List比较,他还是有一个优点的,就是他可以存储类型不一样的对象数据,而List泛型集合类,其中T必须是对他存储元素对象的约束,必须一致性!
ArrayList存储的对象如果是值类型,那就涉及到装箱操作,这个对程序性能影响很大,所以不到万不得已,还是不要用!
而且ArrayList里面存放元素对象类型都不一致,在C#(强类型语言)中处理时,还需要判断,还要涉及到频繁装箱拆箱,性能不说,这不是自讨苦吃嘛....
其实就跟强类型语言和弱类型语言一样,如果把js比作弱类型,那ts就是强类型,js写起来很爽(var声明变量时,变量几乎可以是任意类型...),但是出现报错、异常,找起来会相当麻烦,因为写的时候,约束的少,那最后运行的时候,都会补回来的!而ts有类型约束以后,写起来有了一些束手束脚,但是基本不会出错,而且写多了都一样!这就是大部分后端语言都是强类型的一个重要原因吧(个人观点....)!
List特点:只能添加一种数据类型,可以是基本的值类型也可以实引用类型,一旦数据类型确定,不可更改!
List做数据处理时,完全可以采用强大的Linq,处理起来那是相当的方便\
去重、交集、并集、差集操作
注:这里仅介绍当List中T为引用类型(对象)时,基本类型(值类型)就不说了,因为可以直接用!....引用类型则不行!
另外还一个类型比较特殊,也要单独拿出来提一嘴,就是string,在C#中它属于引用类型,但是它类似于值类型,可以直接进行比较,在这完全可以归属到值类型当中了。
当然使用Linq中GoupBy + Select等方法还是可以做到去重的,但是这里说的并不是这些东西,而是直接使用
Intersect
、Except
、Distinct
、Union
那么为什么引用类型不能直接比较呢,其实稍微懂一点底层的都知道,引用类型,引用两个字就道出了缘由!其值为一个引用地址,在栈内存中,地址是唯一的,但是也有可能两个地址指向同一个堆中的值呢....
因此要想比较,先把他的值点出来比较,可以只比较某一个值,也可以是全部
重写Equals() 和 GetHashCode()
为什么要重新呢,因为这些比较方法的内部就是调用者两个方法进行比较的,他们仅适用于值类型的比较,对象需要重写内部逻辑了!
要想重写,需要写一个类,继承IEqualityComparer接口即可
public class MyComparer : IEqualityComparer<Person>
{
public bool Equals([AllowNull] Person x, [AllowNull] Person y)
{
return x.name == y.name && x.age == y.age;
}
public int GetHashCode([DisallowNull] Person obj)
{
return obj.name.GetHashCode() + obj.age.GetHashCode();
//return obj.name.GetHashCode() ^ obj.age.GetHashCode();// 两种写法都可以
}
}
其实上面写法还是有点不严谨
(1)没有null判断,如果某一属性值为空,那就可能抛异常
(2)并未将对象的所有属性进行比较,如上面,仅仅比较名称和年龄,那全国20岁叫张三的人肯定不止一个,达不到目的了(这里仅仅是举个例子,具体比较多少属性,还是根据项目中实际情况而定的...如果有Id,那完全可以比较Id不是更快....)
把(1)加进去重新写一遍
public class MyComparer : IEqualityComparer<Person>
{
public bool Equals([AllowNull] Person x, [AllowNull] Person y)
{
if(x == null || y == null) return false;
if(x.name == y.name && x.age == y.age) return true;
return false;
}
public int GetHashCode([DisallowNull] Person obj)
{
if(obj == null) return 0;
return obj.name.GetHashCode() + obj.age.GetHashCode();
//return obj.name.GetHashCode() ^ obj.age.GetHashCode();// 两种写法都可以
}
}
简单使用
交集
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//交集:集合A.Intersect(集合B)
var _old = new List<Person> {
new Person{name="zs",age=21},
new Person{name="ls",age=10},
new Person{name="ww",age=13},
new Person{name="ls",age=10},
new Person{name="ww",age=13}
};
var _new = new List<Person> {
new Person{name="zs",age=21},
new Person{name="ls",age=31},
new Person{name="ww3",age=13}
};
var _obj = _old.Intersect(_new,new MyComparer()).ToList();
for (int i = 0; i < _obj.Count; i++)
{
var x = _obj[i];
Console.WriteLine("name:{0},age:{1}", x.name, x.age);
//结果: name:zs,age:21
}
Console.ReadLine();
}
}
public class Person
{
public string name { get; set; }
public int age { get; set; }
}
}
差集
var _oj2 = _old.Except(_new, new MyComparer()).ToList();
//结果:
name:ls,age:10
name:ww,age:13
并集
var _oj2 = _old.Union(_new, new MyComparer()).ToList();
//结果:
name:zs,age:21
name:ls,age:10
name:ww,age:13
name:ls,age:31
name:ww3,age:13
去重
var _oj2 = _old.Distinct(new MyComparer()).ToList();
//结果:
name:zs,age:21
name:ls,age:10
name:ww,age:13
来源:https://juejin.cn/post/7102414161233051684


猜你喜欢
- 一、java端首先我使用的是java自带的对webservice的支持包来编写的服务端和发布程序,代码如下。webservice的接口代码:
- 前言SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文
- 1 什么是条件变量condition_variable是一个类,常和mutex搭配使用。condition_variable类是一个同步原语
- 本文实例讲述了Android编程实现为ListView创建上下文菜单(ContextMenu)的方法。分享给大家供大家参考,具体如下:Con
- malloc的全称是memory allocation,中文叫动态内存分配,用于申请一块连续的指定大小的内存块区域以void*类型返回分配的
- 引言Spring Boot的一个便捷功能是外部化配置,可以轻松访问属性文件中定义的属性。本文将详细介绍@ConfigurationPrope
- 需求:字符串(字符串只有一位小数)转float进行运算, 将结果转成字符串(保留一位小数)直接上代码:float f1 = 0.1f;Str
- Spring Data JPA查询方式及方法名查询规则Spring Data JPA通过解析方法名创建查询在执行查询时,Spring Dat
- 前言在开发 Flutter 应用程序时,我们需要有一个组件来管理全局设置,包括主题、导航和路由。这就是 MaterialApp 的用途。作为
- 前言列表在我们的日常开发中使用的频率是非常高的,像下图的歌曲播放列表,或者课程展示,那么这些场景都需要我们用到点击事件,点击歌曲播放歌曲,点
- 1.循环遍历private void GetControls(Control fatherControl){ Co
- 本文介绍了Android 仿微信自定义数字键盘的实现代码,分享给大家,希望对大家有帮助最终效果:实现这个自定义键盘的思路很简单:要写出一个数
- 避免多线程同时读写共享数据在实际开发中,难免会遇到多线程读写共享数据的需求。比如在某个业务处理时,先获取共享数据(比如是一个计数),再利用共
- 一 悬浮窗口特点:① 窗口一般较小,有时为不规则背景;② 置顶显示;③ 窗口支持拖动;④ 一般用于程序状态显示,比如显示下载进度;⑤ 一般支
- 有时候我们做Android开发,需要弹一个用户提示,但是有时候设计的提示弹窗是带有图片的,我们每次写一个特别麻烦。所以我特地封装了一个工具类
- 一、背景介绍在微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使用HTTP客户端。我们可以使用JDK原生的URLCo
- WebServiceHelper代码:using Microsoft.CSharp;using System;using System.Co
- 当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。导致竞态条件发生的代码区称作临界区。在临界区中使用适当的同步就可以避免
- 结构化查询语言(SQL)是一种标准化的语言,它允许你在数据库上执行操作,如创建项目,读取内容,内容更新和删除条目。SQL是所有可能会使用几乎
- C#将DLL打包到程序中有时候我们的程序中包含一些添加的DLL文件,使用起来不方便,我们可以把这些DLL文件打包到程序集中,只剩下一个EXE