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

Java 核心筆記:hashCode/equals 契約與 I/O 流體系

     編輯:Java 相關知識

記錄 Java 基礎核心知識點:hashCode/equals 協議、哈希表原理、I/O 流分類、緩衝機制、文件讀取最佳實踐。

hashCode 與 equals 深度解析

核心契約

  1. 一致性: a.equals(b) → a.hashCode() == b.hashCode()
  2. 非對稱性: hashCode 相等 ≠ equals 相等(哈希碰撞)
  3. 重寫原則: 覆寫 equals 必須覆寫 hashCode

JVM 內部機制

  • Object.hashCode():通常基於對象地址(Native 實現)
  • 哈希表(HashMap/HashSet)存取流程:
    1. 計算 key.hashCode()
    2. 定位桶索引:(n-1) & hash
    3. 桶內鏈表/紅黑樹遍歷,調用 equals() 精確匹配
  • 自定義類作 Key 必須重寫雙方法,否則按引用比較導致「邏輯相等但無法查找」

常見實現模式


@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    User user = (User) o;
    return id == user.id && Objects.equals(name, user.name);
}

@Override
public int hashCode() {
    return Objects.hash(id, name); // JDK 7+ 推薦
}

I/O 流體系全景

維度字節流字符流
基本單位Byte (8 bits)Char (16 bits, UTF-16)
抽象基類InputStream / OutputStreamReader / Writer
處理對象所有數據(圖片、視頻、二進制)純文本(需編碼轉換)
轉換橋樑InputStreamReader / OutputStreamWriter指定 Charset 實現字節↔字符轉換

緩衝:性能分水嶺


// 無緩衝:每次 1 字節系統調用,極慢
while (in.read() != -1) count++;  // 64KB 文件 → 64K 次調用

// 有緩衝:批量讀入內存數組,用戶態拷貝
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
    byte[] buf = new byte[8192];
    int len;
    while ((len = bis.read(buf)) != -1) count += len; // 64KB → 8 次調用
}

緩衝原理

  • 內部維護 byte[]/char[] 緩衝區(默認 8KB)
  • 系統調用填滿緩衝區,後續 read() 直接從數組拷貝
  • BufferedReader.readLine() 按行讀取,極大簡化文本處理

文件讀取最佳實踐


// JDK 7+ try-with-resources 確保關閉
public long fileLength(Path path) throws IOException {
    try (InputStream in = Files.newInputStream(path)) {
        byte[] buf = new byte[8192];
        long count = 0;
        int len;
        while ((len = in.read(buf)) != -1) count += len;
        return count;
    }
}

// 大文件複製
Files.copy(src, dst, StandardCopyOption.REPLACE_EXISTING);

// 文本逐行處理
Files.lines(path, StandardCharsets.UTF_8)
     .filter(line -> !line.startsWith("#"))
     .forEach(System.out::println);

避坑清單

  • ❌ 字節流直接轉 String:new String(bytes) 隱式用平台默認編碼 → 亂碼
  • ❌ 忘記 close():文件句柄洩漏、數據未刷新、鎖佔用
  • ❌ 循環中創建流對象:重複打開同一文件
  • ✅ 統一指定 StandardCharsets.UTF_8
  • ✅ 善用 Files / Paths (NIO.2) 簡化代碼
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved