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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java hashmap 去重复_为什么我在Java HashMap中得到重复的键?

發(fā)布時間:2025/3/20 java 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java hashmap 去重复_为什么我在Java HashMap中得到重复的键? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本問題已經(jīng)有最佳答案,請猛點這里訪問。

我似乎在標準Java HashMap中得到重復(fù)的鍵。"重復(fù)"是指鍵的equals()方法相等。這是有問題的代碼:

import java.util.Map;

import java.util.HashMap;

public class User {

private String userId;

public User(String userId) {

this.userId = userId;

}

public boolean equals(User other) {

return userId.equals(other.getUserId());

}

public int hashCode() {

return userId.hashCode();

}

public String toString() {

return userId;

}

public static void main(String[] args) {

User arvo1 = new User("Arvo-Part");

User arvo2 = new User("Arvo-Part");

Map map = new HashMap();

map.put(arvo1,1);

map.put(arvo2,2);

System.out.println("arvo1.equals(arvo2):" + arvo1.equals(arvo2));

System.out.println("map:" + map.toString());

System.out.println("arvo1 hash:" + arvo1.hashCode());

System.out.println("arvo2 hash:" + arvo2.hashCode());

System.out.println("map.get(arvo1):" + map.get(arvo1));

System.out.println("map.get(arvo2):" + map.get(arvo2));

System.out.println("map.get(arvo2):" + map.get(arvo2));

System.out.println("map.get(arvo1):" + map.get(arvo1));

}

}

這是結(jié)果輸出:

arvo1.equals(arvo2): true

map: {Arvo-Part=1, Arvo-Part=2}

arvo1 hash: 164585782

arvo2 hash: 164585782

map.get(arvo1): 1

map.get(arvo2): 2

map.get(arvo2): 2

map.get(arvo1): 1

如您所見,

兩個User對象上的equals()方法將返回true,并且它們的哈希碼相同,但是它們各自在map中形成了不同的key。此外,map繼續(xù)區(qū)分最近四個get()調(diào)用中的兩個User鍵。

這直接與文檔相矛盾:

More formally, if this map contains a mapping from a key k to a value v such that (key==null ? k==null : key.equals(k)), then this method returns v; otherwise it returns null. (There can be at most one such mapping.)

這是一個錯誤嗎?我在這里想念什么嗎?我正在運行通過Homebrew安裝的Java版本1.8.0_92。

編輯:此問題已被標記為該另一個問題的重復(fù),但是我將保留該問題,因為它標識出與equals()似乎不一致的地方,而另一個問題假定錯誤在于hashCode() 。希望此問題的存在將使此問題更易于搜索。

嘗試將@Override添加到您的equals和hashCode方法中(始終是最佳實踐),看看是否獲得任何有用的信息。

為了將來出現(xiàn)這種錯別字或錯誤,請始終讓您的IDE為您生成方法。然后調(diào)整它們,使其看起來像您想要的。這將創(chuàng)建帶有@Override批注的正確方法。

問題出在您的equals()方法中。 Object.equals()的簽名是equals(Object),但是在您的情況下,它是equals(USER),因此這是兩個完全不同的方法,并且hashmap使用Object參數(shù)調(diào)用一個方法。您可以通過在等號上放置一個@Override注釋來進行驗證-它將生成編譯器錯誤。

equals方法應(yīng)為:

@Override

public boolean equals(Object other) {

if(other instanceof User){

User user = (User) other;

return userId.equals(user.userId);

}

return false;

}

作為最佳實踐,您應(yīng)始終將@Override放在要覆蓋的方法上-這樣可以省去很多麻煩。

對我來說有趣的問題是:動態(tài)鍵入是否應(yīng)該與呼叫最匹配?可以將Object o = new User(); -> o.equals(o)調(diào)度為與運行時類型最佳匹配。 -但是Java使用靜態(tài)編譯時類型查找正確的重載,而不是動態(tài)運行時參數(shù)-為了完整性,您可以在答案中包括該內(nèi)容!

它將被調(diào)度為最佳的編譯時間類型。 Java沒有動態(tài)類型

嗯,您缺少hasmap被編譯為始終調(diào)用equals(object)的功能,因此,如果您擁有equals(user),它將永遠不會調(diào)用它。但是,如果您在代碼中執(zhí)行User user = new User(); user.equals(new User()),則會調(diào)用equals(user)。但是,如果按照示例Object user = new User(); user.equals(new User())的方式進行操作,則會調(diào)用equals(object)。我希望能清除它

清除了!我認為將其添加到其他用戶的答案中可能會有所幫助:-)

除非明確保證派生類不會成為問題,否則我將避免在等于中使用instanceof。

您的equals方法不會覆蓋equals,并且Map中的類型在運行時會被刪除,因此實際的equals方法為equals(Object)。您的等值線應(yīng)該看起來像這樣:

@Override

public boolean equals(Object other) {

if (!(other instanceof User))

return false;

User u = (User)other;

return userId.equals(u.userId);

}

就像其他人回答的那樣,您對equals方法簽名有疑問。根據(jù)Java equals最佳實踐,您應(yīng)實現(xiàn)以下所示的equals:

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

User user = (User) o;

return userId.equals(user.userId);

}

hashCode()方法同樣適用。請參見覆蓋Java

中的equals()和hashCode()方法

The Second Problem

您現(xiàn)在沒有重復(fù)項,但是您有一個新問題,您的hashMap僅包含一個元素:

map: {Arvo-Part=2}

這是因為兩個User對象都引用相同的String(JVM String Interning),并且從hashMapangular來看,您的兩個對象是相同的,因為這兩個對象在哈希碼中相等,并且均等于方法。因此,當您將第二個對象添加到hashMap時,您將覆蓋第一個對象。

為避免此問題,請確保為每個用戶

使用唯一的ID

A simple demonstration on your users :

好的,所以首先,代碼不會編譯。缺少此方法:

other.getUserId()

但是除此之外,您還需要@Override equals方法,像Eclipse這樣的IDE也可以幫助生成equals和hashCode btw。

@Override

public boolean equals(Object obj)

{

if(this == obj)

return true;

if(obj == null)

return false;

if(getClass() != obj.getClass())

return false;

User other = (User) obj;

if(userId == null)

{

if(other.userId != null)

return false;

}

else if(!userId.equals(other.userId))

return false;

return true;

}

如Chrylis所建議,通過將@Override添加到hashCode和equals中,您將得到編譯錯誤,因為equals方法的簽名是public boolean equals(Object other),因此您實際上并沒有覆蓋默認值。 (來自O(shè)bject類)equals方法。這導致兩個用戶最終都位于hashMap內(nèi)的同一存儲桶中(hashCode被覆蓋,并且兩個用戶具有相同的哈希碼),但是當檢查是否相等時,它們將不同,因為使用了默認的equals方法,這意味著比較內(nèi)存地址。

用以下內(nèi)容替換equals方法以獲得預(yù)期的結(jié)果:

@Override

public boolean equals(Object other) {

return getUserId().equals(((User)other).getUserId());

}

equals不應(yīng)拋出(如果類型不匹配,您的版本將拋出)。

總結(jié)

以上是生活随笔為你收集整理的java hashmap 去重复_为什么我在Java HashMap中得到重复的键?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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