首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

【Java 每日一題】HashSet 存儲 StringBuffer 的 size 陷阱解析

     編輯:Java 綜合教學

【Java 每日一題】HashSet 存儲 StringBuffer 的 size 陷阱解析

今天來看一道經典的集合框架面試題,考察 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()); // 輸出多少?
    }
}

核心分析

  1. HashSet 依賴 hashCode() 與 equals() 判斷元素唯一性;
  2. StringBuffer 未重寫 equals() 和 hashCode(),繼承自 Object,因此比較的是引用地址而非內容;
  3. 四個 new StringBuffer("123") 在堆中創建了四個不同對象,引用各不相同;
  4. 故 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;
  • IDE 可自動生成 equals/hashCode(基於業務關鍵字段),切勿手寫邏輯錯誤。

題目來源:公眾號/簡書「Java每日一題」20161205

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved