MAC 地址(如 00:1A:2B:3C:4D:5E)本質是 48 位無符號整數。去掉冒號後按十六進制解析為 long,即可用數值運算實現區間遍歷、計數、比較,避免字符串處理的低效與易錯。
public final class MacAddressUtils {
private MacAddressUtils() {}
/** 標準化 MAC:大寫、五個冒號、兩位一組 */
public static String normalize(String mac) {
String hex = mac.replaceAll("[:-]", "").toUpperCase();
if (hex.length() != 12) throw new IllegalArgumentException("Invalid MAC: " + mac);
StringBuilder sb = new StringBuilder(17);
for (int i = 0; i < 12; i += 2) {
if (i > 0) sb.append(':');
sb.append(hex, i, i + 2);
}
return sb.toString();
}
/** MAC → long */
public static long toLong(String mac) {
return Long.parseLong(mac.replaceAll("[:-]", ""), 16);
}
/** long → 標準 MAC */
public static String fromLong(long value) {
return String.format("%012X", value)
.replaceAll("(.{2})", "$1:")
.replaceAll(": $", ""); // 移除末尾冒號
}
/** 區間遍歷(含邊界) */
public static void forEachInRange(String startMac, String endMac, Consumer<String> action) {
long start = toLong(normalize(startMac));
long end = toLong(normalize(endMac));
if (start > end) throw new IllegalArgumentException("start > end");
for (long i = start; i <= end; i++) {
action.accept(fromLong(i));
}
}
/** 區間總數 */
public static long countInRange(String startMac, String endMac) {
return toLong(normalize(endMac)) - toLong(normalize(startMac)) + 1;
}
}
public static void main(String[] args) {
String start = "00:1A:2B:00:00:00";
String end = "00:1A:2B:00:00:0F";
System.out.println("總數:" + MacAddressUtils.countInRange(start, end)); // 16
System.out.println("遍歷:");
MacAddressUtils.forEachInRange(start, end, System.out::println);
/* 輸出:
00:1A:2B:00:00:00
00:1A:2B:00:00:01
...
00:1A:2B:00:00:0F
*/
}
百萬級區間單線程遍歷耗時,可結合 Spliterator 並行流:
public static Stream<String> parallelRange(String startMac, String endMac) {
long start = toLong(normalize(startMac));
long end = toLong(normalize(endMac));
return LongStream.rangeClosed(start, end)
.parallel()
.mapToObj(MacAddressUtils::fromLong);
}
// 並行批量入庫示例
parallelRange(start, end)
.collect(Collectors.groupingBy(s -> s.hashCode() % 10)) // 簡單分桶
.values().parallelStream()
.forEach(batch -> jdbcTemplate.batchUpdate(sql, batch));
| 坑點 | 後果 | 對策 |
|---|---|---|
| 輸入格式不統一(大小寫、分隔符) | 解析異常或結果錯誤 | 統一 normalize() 預處理 |
| 跨 OUI 區間(前 3 字節不同) | 遍歷出無效 MAC | 按 OUI 拆分多個子區間 |
| 超長區間導致 OOM/超時 | 服務不可用 | 分批、異步、並行流、斷點續傳 |
| 忽略 MAC 組播/本地管理位 | 生成保留地址 | 業務層校驗第 1 字節第 2 位(U/L bit) |
以 long 為核心數據模型,封裝標準化轉換、區間遍歷、並行流支持,構建可復用的 MacAddressUtils。這不僅解決當前問題,更為設備管理、網絡審計、資產發現等場景奠定高效基礎設施。