真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

怎么解決使用Hashcode中distinct()方法沒有起效問題

本篇內(nèi)容介紹了“怎么解決使用Hashcode中distinct()方法沒有起效問題”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

堅(jiān)守“ 做人真誠 · 做事靠譜 · 口碑至上 · 高效敬業(yè) ”的價值觀,專業(yè)網(wǎng)站建設(shè)服務(wù)10余年為成都成都iso認(rèn)證小微創(chuàng)業(yè)公司專業(yè)提供成都定制網(wǎng)站營銷網(wǎng)站建設(shè)商城網(wǎng)站建設(shè)手機(jī)網(wǎng)站建設(shè)小程序網(wǎng)站建設(shè)網(wǎng)站改版,從內(nèi)容策劃、視覺設(shè)計、底層架構(gòu)、網(wǎng)頁布局、功能開發(fā)迭代于一體的高端網(wǎng)站建設(shè)服務(wù)。

大佬的疑惑

大佬在項(xiàng)目中寫了類似這樣的一段代碼:

List list = new ArrayList<>(); // 省略add數(shù)據(jù)操作 List models =  list.stream().map(ProjectId::getDeviceModel).distinct().collect(Collectors.toList()); System.out.println(models);

結(jié)果呢,這段代碼中的distinct()方法并沒有起效,并沒有達(dá)到去重的預(yù)期。

通過API文檔來看并沒有問題,進(jìn)而大佬開啟了debug模式,發(fā)現(xiàn)奇怪的是實(shí)體類的equals方法都沒進(jìn)。

解決思路

根據(jù)大佬發(fā)的部分代碼和實(shí)現(xiàn)思路,把整個模擬的測試程序補(bǔ)充完整,創(chuàng)建了兩個實(shí)體類ProjectId和DeviceModel,并重寫了equals方法(跟大佬溝通,他重寫了equals方法,并且單獨(dú)使用是生效的)。

DeviceModel實(shí)體類,簡單重寫了equals方法,只比較字段no是否相等。

@Data public class DeviceModel {      private String no;      @Override     public String toString(){         return no;     }      @Override     public boolean equals(Object other) {          if (this == other) {             return true;         }         if (other == null || getClass() != other.getClass()) {             return false;         }          return this.toString().equals(other.toString());     } }

ProjectId實(shí)體類,重寫了equals方法,

@Data public class ProjectId {      private int id;      private DeviceModel deviceModel; }

然后,構(gòu)建了測試類:

public class Test {      public static void main(String[] args) {          List list = new ArrayList<>();          DeviceModel device1 = new DeviceModel();         device1.setNo("1");         ProjectId projectId1 = new ProjectId();         projectId1.setDeviceModel(device1);         projectId1.setId(1);         list.add(projectId1);          DeviceModel device2 = new DeviceModel();         device2.setNo("1");         ProjectId projectId2 = new ProjectId();         projectId2.setDeviceModel(device2);         projectId2.setId(1);         list.add(projectId2);          DeviceModel device3 = new DeviceModel();         device3.setNo("2");         ProjectId projectId3 = new ProjectId();         projectId3.setDeviceModel(device3);         projectId3.setId(2);         list.add(projectId3);                 List models =  list.stream().map(ProjectId::getDeviceModel).distinct().collect(Collectors.toList());        System.out.println(models);      } }

先構(gòu)建了一組數(shù)據(jù),然后讓device1與device2的no屬性一樣,重寫了equals方法,理論上它們應(yīng)該是相等的,device3對象用來做對照。

執(zhí)行上面的程序,控制臺打印如下:

[1, 1, 2]

的確還原了大佬的bug,也奇怪為什么會這樣。但既然bug已重現(xiàn),解決就是比較簡單的事了。

此時,大佬又發(fā)來另外一個線索,說通過for循環(huán)形式?jīng)]事:

List results = new ArrayList<>(); for (DeviceModel deviceModel : list.stream().map(ProjectId::getDeviceModel).collect(Collectors.toList())) {     if (!results.contains(deviceModel)) {         results.add(deviceModel);     } } System.out.println(results);

這種實(shí)現(xiàn)形式恰好又可以用來做對照。

問題排查

進(jìn)行問題排查時首先也想到了debug,但是同樣出現(xiàn)并未走equals方法的情況。

仔細(xì)看了一下代碼,發(fā)現(xiàn)在Stream處理的過程中用到了map操作。而在之前的文章中也提到,Map中判斷一個對象是否已經(jīng)存在是先通過key的hash值定位到對應(yīng)的數(shù)組下標(biāo),如果該位置上的Entry沒有值,則直接保存;如果已經(jīng)有存在的值,再通過equals方法比較值是否一樣。

那么,是不是因?yàn)橹貙懥薳quals方法,而沒有重寫hashcode方法導(dǎo)致的呢?于是,在DeviceModel類中新增了hashcode方法:

@Override public int hashCode() {     // JDK7新增的Objects工具類     return Objects.hash(no); }

再次執(zhí)行,測試方法,發(fā)現(xiàn)可以成功去重了。很顯然,大佬的失誤是在重寫equals方法時違背了一條原則:如果一個類的equals方法相等,那么它們的hashcode方法必須相等。由于沒有重寫hashcode方法導(dǎo)致違背這一原則。因此,在隱式使用Map時就出現(xiàn)了莫名其妙的問題。

后續(xù)

經(jīng)過這一番周折,問題終于解決。想必大家更也更加明白了為什么重寫equals方法一定要重寫hashcode方法了。后面大佬又考問我一個問題:為什么list.contains方法不會出現(xiàn)這個問題呢?

因?yàn)長ist的底層結(jié)構(gòu)是數(shù)組,不像Map那樣為了提升效率先對Key進(jìn)行hash處理比較。簡單看一下ArrayList中contains方法的核心實(shí)現(xiàn):

public int indexOf(Object o) {     if (o == null) {         for (int i = 0; i < size; i++)             if (elementData[i]==null)                 return i;     } else {         for (int i = 0; i < size; i++)             if (o.equals(elementData[i]))                 return i;     }     return -1; }

可以看出如果對象不為null時,還是循環(huán)調(diào)用的equals方法來處理的。

“怎么解決使用Hashcode中distinct()方法沒有起效問題”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!


當(dāng)前題目:怎么解決使用Hashcode中distinct()方法沒有起效問題
文章位置:http://weahome.cn/article/pdhped.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部