今天來看一道經典的集合框架面試題,考察 HashSet 去重邏輯與 StringBuffer 的 equals/hashCode 契約。
package Dec2016;
import java.util.HashSet;
public class Ques1205 {
public static void main(String[] args){
StringBuffer sb1 = new StringBuffer("123");
StringBuffer sb2 = new StringBuffer("123");
StringBuffer sb3 = new StringBuffer("123");
StringBuffer sb4 = new StringBuffer("123");
HashSet<StringBuffer> set = new HashSet<>();
set.add(sb1);
set.add(sb2);
set.add(sb3);
set.add(sb4);
System.out.println(set.size()); // 輸出多少?
}
}
HashSet 依賴 hashCode() 與 equals() 判斷元素唯一性;StringBuffer 未重寫 equals() 和 hashCode(),繼承自 Object,因此比較的是引用地址而非內容;new StringBuffer("123") 在堆中創建了四個不同對象,引用各不相同;set.add() 四次全部成功,size() 返回 4。若改用 String(已重寫 equals/hashCode 基於內容),結果為 1:
HashSet<String> set = new HashSet<>();
set.add("123");
set.add("123");
System.out.println(set.size()); // 1
Set 元素或 Map 鍵時,務必重寫 equals() 和 hashCode();StringBuffer/StringBuilder 設計為可變字符序列,不適合作為集合鍵值,優先使用 String;題目來源:公眾號/簡書「Java每日一題」20161205