網站首頁 編程語言 正文
前天在做批量數據導入新增時,要對數據進行有效性判斷,其中還要去除重復,如果沒出現linq的話可能會新聲明一個臨時對象集合,然后遍歷原始數據判斷把符合條件的數據添加到臨時集合中,這在有了linq之后顯得比較麻煩。
一、首先創建一個控制臺應用程序,添加一個Person對象
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Compare
{
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
this.Name = name;
this.Age = age;
}
}
}
二、創建測試數據
創建了一個Name="ZhangSan"的Person對象,放入personList兩次,然后personList又創建了幾個Person對象,這幾個Person對象中也有Name、Age都重復的。例如:"XiaoMing",26.
Person person = new Person("ZhangSan",26);
List<Person> personList = new List<Person>() {
person,
new Person("XiaoMing",25),
new Person("CuiYanWei",25),
new Person("XiaoMing",26),
new Person("XiaoMing",25),
new Person("LaoWang",26),
new Person("XiaoMing",26),
person
};
三、測試
下面的代碼中用了兩種方式來選擇不重復的數據。
List<Person> defaultDistinctPersons = personList.Distinct().ToList<Person>();
foreach (Person p in defaultDistinctPersons)
{
Console.WriteLine("Name:{0} Age:{1}",p.Name,p.Age);
}
Console.WriteLine("-----------------------------------------------------");
List<Person> comparePersons = personList.Distinct(new PersonCompare()).ToList<Person>();
foreach (Person p in comparePersons)
{
Console.WriteLine("Name:{0} Age:{1}", p.Name, p.Age);
}
Console.ReadLine();
在華麗分割線上面是使用默認的distinct,下面是通過集成IEqualityComparer接口。下面是實現接口的代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Compare
{
public class PersonCompare:IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
if (x == null || y == null)
return false;
return x.Name.Equals(y.Name) && x.Age == y.Age;
}
public int GetHashCode(Person obj)
{
return obj.GetHashCode();
}
}
}
在上面的代碼中,繼承IEqualityComparer接口,主要是實現了兩個方法:bool Equals(T x, T y);int GetHashCode(T obj);可能即使實現了接口也不了解里面是怎么個原理,我們先看下運行結果。
從上面的運行結果可以看到,兩個運行結果是一樣的,還是有重復的數據:例如XiaoMing,26.兩個都沒去除重復,只有ZhangSan那兩個去除重復了。是不是有實現接口多此一舉的感覺。那為什么還要有這個接口還要實現它呢?其實要說下GetHashCode和Equals。
在說GetHashCode和Equals之前先了解下distinct(),這個方法Distinct 默認比較的是對象的引用,所以使用默認的distinct()方法是ZhangSan對象是過濾除去的,而XiaoMing,26是兩個不同的對象,沒有除去。
然后說下GetHashCode和Equals兩個方法.
1.哈希碼哈希代碼是一個用于在相等測試過程中標識對象的數值。它還可以作為一個集合中的對象的索引。如果兩個對象的 Equals 比較結果相等,則每個對象的 GetHashCode 方法都必須返回同一個值。 如果兩個對象的比較結果不相等,這兩個對象的 GetHashCode 方法不一定返回不同的值.
簡而言之,如果你發現兩個對象 GetHashCode() 的返回值相等,那么這兩個對象就很可能是同一個對象;但如果返回值不相等,這兩個對象一定不是同一個對象.
當GetHashCode可以直接分辨出不相等時,Equals就沒必要調用了,而當GetHashCode返回相同結果時,Equals方法會被調用從而確保判斷對象是否真的相等。所以,還是那句話:GetHashCode沒必要一定把對象分辨得很清楚(況且它也不可能,一個int不可能代表所有的可能出現的值),有Equals在后面做保障。GetHashCode僅需要對對象進行快速判斷。
上面的幾句算是總結性的說明了兩個方法的是怎么個路子,這也能解釋出ZhangSan的重復去除,而其他的幾個對象沒有去重復的原因,ZhangSan那是一個對象,其他的雖然Name、Age相等,但不是同一個對象。
我們可以稍微改動下代碼來驗證上面的語句.在實現IEqualityComparer的接口類中打印出一些信息就能看明白
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Compare
{
public class PersonCompare:IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
if (x == null || y == null)
return false;
Console.WriteLine("XName:{0} XAge:{1} XHashCode:{2} YName:{3} YAge:{4} YHashCode:{5}", x.Name, x.Age, x.GetHashCode(),y.Name,y.Age,y.GetHashCode());
return x.Name.Equals(y.Name) && x.Age == y.Age;
}
public int GetHashCode(Person obj)
{
Console.WriteLine("GetHashCode Name:{0} Age:{1} HashCode:{2}",obj.Name,obj.Age,obj.GetHashCode());
return obj.GetHashCode();
}
}
}
在GetHashCode中打印了對象的Name、Age和HashCode。可以看到HashCode只有ZhangSan的是相同的,在Equals方法中只打印出了ZhangSan的,還是因為上面的先判斷HashCode,相等了再使用Equals判斷。
我們再改動下實現IEqualityComparer的接口類
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Compare
{
public class PersonCompare:IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
if (x == null || y == null)
return false;
Console.WriteLine("XName:{0} XAge:{1} XHashCode:{2} YName:{3} YAge:{4} YHashCode:{5}", x.Name, x.Age, x.GetHashCode(), y.Name, y.Age, y.GetHashCode());
return x.Name.Equals(y.Name) && x.Age == y.Age;
}
public int GetHashCode(Person obj)
{
//Console.WriteLine("GetHashCode Name:{0} Age:{1} HashCode:{2}",obj.Name,obj.Age,obj.GetHashCode());
//return obj.GetHashCode();
string s = string.Format("{0}_{1}",obj.Name,obj.Age);
Console.WriteLine("Name:{0} Age:{1} HashCode:{2}",obj.Name,obj.Age, s.GetHashCode());
return s.GetHashCode();
}
}
}
根據上面的的代碼和測試結果我們可以看到,GetHashCode執行了7次(7個對象),Equals執行了3次,因為ZhangSan,26和XiaoMing,25兩個的哈希碼是一樣的就沒有繼續往下執行。
原文鏈接:https://www.cnblogs.com/5ishare/p/5730337.html
- 上一篇:C++超詳細介紹模板_C 語言
- 下一篇:C++示例講解初始化列表方法_C 語言
相關推薦
- 2022-10-29 關于torch.load加載預訓練模型時 造成的 臨時分配的顯存 不釋放
- 2022-07-02 jquery實現無縫輪播圖_jquery
- 2023-04-01 路由react-router-dom的基本使用教程_React
- 2022-10-15 使用Pycharm創建一個Django項目的超詳細圖文教程_python
- 2022-06-21 Windows下安裝Git_其它綜合
- 2022-06-28 python神經網絡使用tensorflow構建長短時記憶LSTM_python
- 2022-06-14 Pycharm安裝第三方庫的超詳細步驟_python
- 2022-08-28 Spring Boot整合ElasticSearch
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支