0%

Java 中的哈希(Hash)机制:HashMap 与 Hashtable 的实现对比

哈希(Hash)是 Java 集合框架中实现高效存储和查询的核心机制,尤其是在 HashMapHashtable 中,哈希算法的设计直接影响哈希冲突的概率和性能。本文将深入解析两者的哈希计算方法、索引定位逻辑及优化策略,揭示其减少哈希碰撞的底层原理。

哈希的核心目标

哈希的核心是通过哈希函数将任意长度的输入(如对象的 hashCode)映射到固定长度的输出(如数组索引),目标是:

  1. 均匀分布:使键值对在数组中均匀分布,减少哈希冲突(不同键映射到同一索引);
  2. 高效计算:哈希函数和索引计算应简单快速,避免额外性能损耗。

HashMap 的哈希机制(JDK 1.8)

HashMap 采用 “二次哈希 + 与运算” 的方式,通过扰动函数增强哈希值的随机性,减少冲突。

哈希值计算(扰动函数)

HashMap 对键的原始哈希值(key.hashCode())进行二次处理,代码如下:

1
2
3
4
5
6
static final int hash(Object key) {
int h;
// 1. 若 key 为 null,哈希值为 0;否则计算 h = key.hashCode()
// 2. 高 16 位与低 16 位异或(h ^ (h >>> 16)),增强随机性
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
扰动的原因:
  • 原始 hashCode 是 32 位整数,但数组容量(n)通常较小(默认 16,最大 2^30),导致计算索引时仅低 log2(n) 位有效(高位被忽略)。
  • 例如:若两个键的 hashCode 高位不同但低位相同,直接使用原始哈希值会导致索引冲突。
  • 扰动通过 “高 16 位异或低 16 位”,将高位信息混入低位,增加低位的随机性,减少冲突。

索引计算(与运算)

通过扰动后的哈希值计算数组索引:

阅读全文 »

Nginx 反向代理配置详解:从基础到高级应用

反向代理是 Nginx 最核心的功能之一,通过将客户端请求转发到后端服务器(如应用服务器、静态资源服务器等),实现请求分发、隐藏真实服务地址、负载均衡等效果。本文详细讲解 Nginx 反向代理的配置方法、核心参数及不同场景的实战案例。

反向代理基础配置

Nginx 通过proxy_pass指令实现反向代理,核心是在location块中定义转发规则,将匹配的请求转发到指定的后端服务。

1. 最简单的反向代理

将所有请求转发到单个后端服务(如本地 8080 端口的 Java 应用):

1
2
3
4
5
6
7
8
9
server {
listen 80; # Nginx监听80端口
server_name example.com; # 绑定域名

# 匹配所有根路径请求
location / {
proxy_pass http://127.0.0.1:8080; # 转发到后端服务
}
}
  • 效果:客户端访问http://example.com时,Nginx 会将请求转发到http://127.0.0.1:8080,并将后端响应返回给客户端。

2. 按路径转发到不同服务

根据请求路径的不同,转发到不同的后端服务(如区分 API 服务和静态资源服务):

阅读全文 »

Linux 用户与组管理详解:权限控制的核心机制

Linux 是多用户多任务操作系统,用户与组的管理是系统安全和权限控制的基础。本文将系统讲解用户与组的配置文件、核心管理命令及权限控制逻辑,帮助你掌握 Linux 下的身份管理体系。

用户管理:从配置文件到核心命令

Linux 通过 /etc/passwd/etc/shadow 存储用户信息,通过一系列命令实现用户的创建、修改和删除。

用户信息文件解析

(1)/etc/passwd:用户基本信息

该文件记录所有用户的公开信息,每行对应一个用户,以冒号分隔为 7 个字段:

1
2
3
4
5
6
7
8
9
root:x:0:0:root:/root:/bin/bash
# 字段含义:
# 1. 用户名(root)
# 2. 密码标志(x 表示密码存储在 /etc/shadow)
# 3. UID(用户ID,0 为超级用户,1-499 为系统用户,500+ 为普通用户)
# 4. GID(初始组ID,对应 /etc/group)
# 5. 用户说明(可选,如 root 描述)
# 6. 家目录(/root 为 root 主目录,普通用户默认 /home/用户名)
# 7. 登录Shell(/bin/bash 为可交互Shell,/sbin/nologin 为禁止登录)
(2)/etc/shadow:用户密码信息

存储用户密码的加密信息(仅 root 可读写),每行对应一个用户,以冒号分隔为 9 个字段:

1
2
3
4
5
6
7
8
9
10
11
root:$6$xxxxxxxx$xxxxxx:19500:0:99999:7:::
# 字段含义:
# 1. 用户名(root)
# 2. 加密密码($6$ 表示 SHA-512 加密,* 或 ! 表示账号锁定)
# 3. 最近修改密码时间(距离 1970-01-01 的天数)
# 4. 密码修改间隔(0 表示随时可改)
# 5. 密码有效期(99999 表示永不过期)
# 6. 密码到期前警告天数(7 天前警告)
# 7. 密码到期后宽限天数(过期后仍可登录的天数)
# 8. 账号失效时间(空表示永不过期)
# 9. 保留字段

用户管理核心命令

(1)创建用户:useradd
阅读全文 »

Nginx 变量参数详解:从基础使用到条件判断

Nginx 提供了丰富的内置变量(参数),可用于获取请求信息、服务器状态等数据,结合条件判断(if语句)能实现灵活的请求处理逻辑。本文系统梳理 Nginx 常用变量的含义、使用场景及条件判断语法,帮助开发者高效配置 Nginx。

核心内置变量:获取请求与服务器信息

Nginx 的内置变量以$开头,可在配置文件中直接引用,用于动态获取请求参数、客户端信息、服务器状态等。以下是最常用的变量分类及说明:

请求参数与 URI 相关变量

变量 含义 示例
$arg_NAME 获取 HTTP 请求中指定参数的值(NAME 为参数名) 请求/index.html?name=zhangsan中,$arg_name的值为zhangsan
$args 请求 URI 中的完整参数(与$query_string相同) 请求/list?id=1&page=2中,值为id=1&page=2
$uri / $document_uri 当前请求的 URI(不带参数,可能被内部重定向修改) 请求/article/123?lang=cn中,值为/article/123
$request_uri 客户端原始请求的完整 URI(带参数,永不改变) 请求/article/123?lang=cn中,值为/article/123?lang=cn
$is_args 若请求带参数则为?,否则为空字符串 带参数时为?,无参数时为空

客户端与连接信息变量

变量 含义 示例
$remote_addr 客户端 IP 地址 192.168.1.100
$remote_port 客户端连接使用的端口 54321
$binary_remote_addr 二进制格式的客户端 IP(节省内存) \x0A\xE0B\x0E(对应10.224.66.14
$http_HEADER 获取客户端请求头中指定字段的值(HEADER 为小写) $http_user_agent获取浏览器标识,$http_referer获取来源页

服务器与响应信息变量

阅读全文 »

DNS 服务器详解:域名解析的核心机制与配置实践

DNS(Domain Name System,域名系统)作为应用层的核心协议,承担着 “域名→IP 地址” 的映射转换工作,是互联网通信的 “基础设施”。它通过分布式服务器架构,将人类易记的域名(如baidu.com)解析为计算机可识别的 IP 地址(如192.168.1.1),极大降低了网络访问的复杂度。以下从原理、配置文件到实战操作,全面解析 DNS 服务器。

DNS 服务器的核心原理

基本功能

  • 域名与 IP 的映射:正向解析(域名→IP)和反向解析(IP→域名)。
  • 分布式架构:通过根服务器、顶级域名服务器(如.com.cn)、权威服务器的层级协作,实现全球域名的高效解析。
  • 缓存机制:本地 DNS 服务器会缓存解析结果,减少重复查询,提升响应速度。

传输层协议

DNS 主要使用UDP 协议(端口 53)进行查询,因其速度快、开销小;当查询数据量大(如超过 512 字节)时,会自动切换到 TCP 协议。

DNS 服务器的关键配置文件

Linux 系统中,DNS 服务(通常为bind)的配置文件分布如下,不同文件各司其职:

阅读全文 »