日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java中的Set对象去重

發(fā)布時(shí)間:2023/12/10 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java中的Set对象去重 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言部分

Set<T> 去重相信大家一定不陌生,尤其是在 Set<String>、Set<Integer> 等等,但是在使用 Set<實(shí)體> ,在不重寫 equals()、hashCode() 方法情況下,直接使用貌似并不能生效。

所以想要 Set<實(shí)體> 實(shí)現(xiàn)去重,核心部分在實(shí)體中重寫 equals()、hashCode() 方法。

如下以 User 實(shí)體為例,進(jìn)行測(cè)試。

代碼部分

測(cè)試代碼:

public static void main(String[] args) {Set<User> userSet = new HashSet<User>(){{add(new User("張三",10));add(new User("張三",20));add(new User("張三",10));}};userSet.forEach(user -> {System.out.println(String.format("name: %s, age:%s",user.getName(),user.getAge()));}); }

打印結(jié)果:

name: 張三, age:20 name: 張三, age:10

實(shí)體對(duì)象(User.java): 重寫了 equals()、hashCodd() 方法。

public class User {public User(String name, Integer age){this.name = name;this.age = age;}/** 姓名 **/private String name;/** 年齡 **/private Integer age;省略get、set方法.../*** 重寫equals方法,如果對(duì)象類型是User,先比較hashcode,一致的場(chǎng)合再比較每個(gè)屬性的值*/@Overridepublic boolean equals(Object obj) {System.out.println("調(diào)用equals方法,當(dāng)前的hashCode為:"+hashCode());/** 對(duì)象是 null 直接返回 false **/if (obj == null) {return false;}/** 對(duì)象是當(dāng)前對(duì)象,直接返回 true **/if (this == obj) {return true;}/** 判斷對(duì)象類型是否是User **/if (obj instanceof User) {User vo = (User) obj;/** 比較每個(gè)屬性的值一致時(shí)才返回true **//** 有幾個(gè)對(duì)象就要比較幾個(gè)屬性 **/if (vo.name.equals(this.name) && vo.age.equals(this.age)) {return true;}}return false;}/*** 重寫hashcode方法,返回的hashCode一樣才再去比較每個(gè)屬性的值*/@Overridepublic int hashCode() {return this.getName().hashCode() * this.getAge().hashCode();}}

解釋部分

為什么 Set<String>、Set<Integer> 就可以直接實(shí)現(xiàn)去重,而 Set<實(shí)體> 就不可以,反而要重寫 equals()、hashCode() 方法才能實(shí)現(xiàn),更甚者是,只重寫 equals() 方法,而不重寫 hashCode() 方法都沒法完成去重~

大家對(duì)這個(gè)問題有過疑惑嗎?

1、HashSet 添加數(shù)據(jù)過程

HashSet 的底層實(shí)現(xiàn),相信大家都清楚是 HashMap 吧?我們?cè)?add() 數(shù)據(jù)時(shí),其實(shí)一層層找,最終是調(diào)的 HashMap 的 put() 方法,如下是 HashSet 的 add() 方法,其中 map 為 HashMap。

我們?cè)冱c(diǎn)一層找到 HashMap 的 put() 方法:

如上圖所示,通過 putVal() 方法我們大致有了個(gè)概念了,判斷是否為舊值就是對(duì) hash 值、key 值進(jìn)行比較。

hash 值比較自然調(diào)用的事 hashCode() 方法,而 key 值的比較實(shí)用的是 equals() 方法。

了解到這基本就可以看出 hashCode() 、equals() 方法對(duì)于去重的重要性了。

2、Set<單屬性> 可以直接使用去重

那么接下來我們就可以來看看 Set<單屬性>(單屬性:String、Integer等),為什么直接使用就可以去重了。

我們以 String 為例,假設(shè)有兩個(gè)字符串 a、b,如下:

String a = "123"; String b = "123"; System.out.println("a.hashCode:"+a.hashCode()); System.out.println("b.hashCode:"+b.hashCode()); System.out.println(a.equals(b));

打印結(jié)果如下:

a.hashCode:48690 b.hashCode:48690 true

很顯然,在沒有重寫 hashCode() 、equals() 方法時(shí),字符串 a、b 的 hashCode,equalse() 是一致的,那么這兩個(gè)就可以視為一個(gè)對(duì)象,所以用在 Set 里面就可以直接去重。

但是為什么會(huì)一致呢?

任何對(duì)象在不重寫 equals()、hashcode() 的情況下,使用的是 Object 對(duì)象的 equals() 方法和 hashcode() 方法,而重點(diǎn)就是,默認(rèn)的 equals() 方法判斷的是兩個(gè)對(duì)象的引用指向的是不是同一個(gè)對(duì)象;而 hashcode 也是根據(jù)對(duì)象地址生成一個(gè)整數(shù)數(shù)值;

顯然字符串 a、b 這兩個(gè)條件都滿足,所以對(duì)于 Set 來說就是一個(gè)對(duì)象的概念。

3、Set<實(shí)體> 去重

但是換到對(duì)于實(shí)體對(duì)象就行不通了,我們?cè)賮硖?Object 的 equals()、hashCode() 方法。

當(dāng)我們 new User() 對(duì)象時(shí),兩個(gè)對(duì)象的地址引用肯定是不同的;其次 hashcode 是根據(jù)對(duì)象地址生成的,這樣顯然也不同,所以對(duì)于 Set 來說,那么去重就行不通。

因此,想要讓 Set<實(shí)體> 實(shí)現(xiàn)去重效果,那么就需要重寫 equals() 、hashCode() 方法。

只有兩個(gè)對(duì)象的 hashCode() 方法的值一致,且 equalse() 方法返回 true,那么這對(duì)于 Set<實(shí)體> 來說就可以看做一個(gè)對(duì)象, 如果兩者只滿足一個(gè)是不可以的(只重寫一個(gè)),舉個(gè)例子:

equales()重寫,hashCode()不重寫

@Override public boolean equals(Object obj) {return true; }//@Override //public int hashCode() { // return this.getName().hashCode() * this.getAge().hashCode(); //}

執(zhí)行代碼:

Set<User> userSet = new HashSet<User>(){{add(new User("張三",10));add(new User("張三",20));add(new User("張三",10)); }};userSet.forEach(user -> {System.out.println(String.format("name: %s, age:%s",user.getName(),user.getAge())); });

打印內(nèi)容:

name: 張三, age:10 name: 張三, age:10

equales()不重寫,hashCode()重寫

//@Override //public boolean equals(Object obj) { // return true; //}@Override public int hashCode() {return this.getName().hashCode() * this.getAge().hashCode(); }

執(zhí)行代碼+打印內(nèi)容如上:

name: 張三, age:10 name: 張三, age:10

總結(jié)

總之,要想保證 Set<實(shí)體> 實(shí)現(xiàn)去重,就需要兩個(gè)實(shí)體 “一致”,這里的一致是只需要滿足如下兩個(gè)條件:

  • 重寫 hashCode() 方法,確保兩者 hashcode 一致,比如使用屬性相乘或者相加。
  • 重寫 equals() 方法,相同對(duì)象、屬性值相同對(duì)象皆為相等。

通過上面這些例子也能看出重寫 equals 方法,就必須重寫 hashCode 的重要性,因?yàn)橹恢貙?equals() 不一定能滿足預(yù)期相等的效果。

如下是阿里巴巴開發(fā)手冊(cè),關(guān)于 hashCode 和 equals 的處理規(guī)則:

希望這篇文章對(duì)你有所幫助。博客園持續(xù)更新,歡迎關(guān)注。

博客園:https://www.cnblogs.com/niceyoo

總結(jié)

以上是生活随笔為你收集整理的Java中的Set对象去重的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 太久av | 操你啦在线视频 | 国产激情一区二区三区视频免樱桃 | a级黄色片免费看 | 韩国av毛片 | 一区二区三区四区五区视频 | wwwxx国产 | 亚洲综合成人亚洲 | 男女野外做受全过程 | 国产亚洲av片在线观看18女人 | 北条麻妃一区二区三区四区五区 | 五月天久久久 | www麻豆 | 国产精品一区免费 | 成人综合社区 | 日韩黄色网络 | 少妇激情偷人爽爽91嫩草 | 日本一区二区三区成人 | 中国一级特黄视频 | 日日摸夜夜 | 农村老熟妇乱子伦视频 | 秋霞欧美视频 | 亚洲精品一区二区三区不卡 | 亚洲第二页 | 欧美视频一区二区在线观看 | 日本一区二区三区欧美 | 香港三日本8a三级少妇三级99 | 色图视频 | 亚洲a毛片 | 亚洲精品在线免费播放 | 台湾性dvd性色av | 久久91 | 91爱看| 久久99久久99精品免视看婷婷 | 国产一区二区在线不卡 | 国产香蕉在线视频 | 国产传媒一区二区三区 | 男男肉耽高h彩漫 | 久草99| 黄色片日韩 | 欧美色啪 | 青青青在线视频观看 | 免费在线成人 | 日韩av一二三区 | 久久久久三级 | 小视频在线| 五月天导航 | 极品少妇xxxx精品少妇 | 亚洲av无码专区在线 | 久久久久无码国产精品不卡 | 久久久久久久久久久久久久久久久久久 | 国产精品一区二区在线看 | av最新在线 | 999精品免费视频 | 91免费网站在线观看 | 亚洲日本激情 | 国产午夜福利100集发布 | 手机看片日韩 | 国产日韩欧美自拍 | 欧美性猛交xxxx乱大交蜜桃 | 午夜资源站 | 99国产揄拍国产精品 | 99热网| 亚洲精选免费 | 欧美性激情 | 麻豆偷拍 | 九九精品在线观看视频 | 国产一级在线 | 成人做爰66片免费看网站 | 久久不射影院 | 日韩美女做爰高潮免费 | 亚洲精品推荐 | 无码国产精品一区二区色情男同 | 欧美乱大交xxxxx潮喷l头像 | 亚洲www | 国产日韩欧美一区二区东京热 | 国产精品igao视频 | 91在线视频网址 | 永久黄色网址 | 国产又大又硬又粗 | 日韩成人av网址 | 国产免费av片在线观看 | 亚洲无吗一区二区三区 | 手机在线看永久av片免费 | 720url在线观看免费版 | 男人猛吃奶女人爽视频 | 国产大片在线观看 | 好吊操这里只有精品 | 国产a一区 | 91视频你懂的| 日韩人妻无码精品久久免费 | 久久精品国产亚洲av麻豆 | 成人日韩欧美 | 欧美日韩成人免费观看 | 欧美日韩一区二区三区视频 | 韩国精品一区二区三区 | 色偷偷免费视频 | 日本东京热一区二区三区 | 精品日韩在线 |