![IST_1183_99214.png|400](https://imagehosting4picgo.oss-cn-beijing.aliyuncs.com/imagehosting/fix-dir%2Ftmp%2F%E5%8D%83%E5%9B%BE_%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%96%87%E4%BB%B6%E5%9C%A8%E7%BA%BF%E6%90%9C%E7%B4%A2%E4%BB%A3%E7%A0%81%E6%94%BE%E5%A4%A7%E9%95%9C_%E5%9B%BE%E7%89%87%E7%BC%96%E5%8F%B769890404%2F2024%2F05%2F02%2F15-28-24-4d32c6186a8465f253c9ff0fd51e9105-IST_1183_99214-7bf59a.png) 在 Java 中十万个长度为 "beijing_123132" 的字符串是多少 M? <!-- more --> - [三个长度单元](#%E4%B8%89%E4%B8%AA%E9%95%BF%E5%BA%A6%E5%8D%95%E5%85%83) - [字符 character 维度](#%E5%AD%97%E7%AC%A6%20character%20%E7%BB%B4%E5%BA%A6) - [字节 Byte 维度](#%E5%AD%97%E8%8A%82%20Byte%20%E7%BB%B4%E5%BA%A6) - [KB,MB](#KB%EF%BC%8CMB) - [位数 Bit 维度](#%E4%BD%8D%E6%95%B0%20Bit%20%E7%BB%B4%E5%BA%A6) - [案例分析](#%E6%A1%88%E4%BE%8B%E5%88%86%E6%9E%90) - [普通情况](#%E6%99%AE%E9%80%9A%E6%83%85%E5%86%B5) - [JVM 中](#JVM%20%E4%B8%AD) - [字符串存储分析](#%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%AD%98%E5%82%A8%E5%88%86%E6%9E%90) - [JVM 中两百万个字符串的总内存占用](#JVM%20%E4%B8%AD%E4%B8%A4%E7%99%BE%E4%B8%87%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E6%80%BB%E5%86%85%E5%AD%98%E5%8D%A0%E7%94%A8) - [注意](#%E6%B3%A8%E6%84%8F) ## 三个长度单元 ### 字符 character 维度 字符不分中西!比如,字符串 " 我爱 b" 由三个字符组成:两个中文字符 " 我 " 和 " 爱 ",以及一个英文字符 "b"。总计,这个字符串是由三个字符构成的。在编码中,字符的数量是指字符串中的元素总数,不论这些字符是属于*哪种语言或符号系统*。 ### 字节 Byte 维度 | 类型 | 字符示例 | ASCII 字节数 | UTF-8 字节数 | UTF-16 字节数 | |------|---------|-----------|-----------|------------| | 英文字符 | A, z, 1 | 1 字节 | *1 字节* | 2 字节 | | 中文字符 | 中, 文 | 不适用 | *3 字节* | 2 字节 | | 特殊符号 | @, #, $ | 1 字节 | 1 字节 | 2 字节 | | 特殊符号 | €, ©, ¼ | 不适用 | 2-3 字节 | 2 字节 | | 表情符号 | 😊, 🚀 | 不适用 | 4 字节 | 4 字节 | UTF-8 里一个中文字符需要 3 字节,Java 里一个 char 是 2byte,如果用 UTF-8 岂不是就不够了,所以其实 Java 用的是 UTF-16 ### KB,MB 知道字节就可以算我们常说的 KB 和 MB 了 1. **1 Kilobyte (KB)**: - **在二进制计数系统中**,1 KB 等于 210210 字节,也就是 1024 字节。 - 因此,1 KB 等于 1024×8=81921024×8=8192 bits。 2. **1 Megabyte (MB)**: - **在二进制计数系统中**,1 MB 等于 220220 字节,也就是 1,048,576 字节。 - 因此,1 MB 等于 1,048,576×8=8,388,6081,048,576×8=8,388,608 bits。 ### 位数 Bit 维度 1 byte = 8 bits 不管啥字符集,1 byte = 8 bits,代表 256 种变换,所以表示英文绰绰有余 UTF-16 里, 2 byte = 16 bits,代表 6w 种变换,表示中文也绰绰有余了 UTF-8 里, 3 byte = 24 bits,代表 1600w 种变换,表示中文 更富裕了 ## 案例分析 > "beijing_11352" 是多少字符,多少 byte,多少 bit?多少 KB?多少 MB? ### 普通情况 200w(个数)* 12(字符数)* 2(由字符集决定)= 40000000 byte = 40MB ### JVM 中 在 Java 虚拟机(JVM)中处理两百万个 "beijing_11352" 字符串的内存占用,还需要考虑到 JVM 对字符串的特殊处理和管理。这包括字符串对象的开销、字符串池的可能影响(如果字符串被内部化),以及字符数组本身的存储开销。 #### 字符串存储分析 1. **基本存储**: - 一个 "beijing_11352" 字符串由 12 个字符组成,使用 UTF-16 编码(Java 的默认字符编码)。在 UTF-16 中,大多数字符(包括所有基本多语言平面(BMP)的字符)占用 2 个字节。因此,每个字符串的字符数组需要 12×2=2412×2=24 bytes。 2. **字符串对象的开销**: - 每个 Java 对象都有一个对象头。在大多数 64 位 JVM 上,对象头通常占用 12 bytes。另外,对于数组对象,还需要额外的空间来存储长度信息,通常是 4 bytes。 - 因此,每个字符串对象的总开销包括对象头和字符数组的开销:12+4+24=4012+4+24=40 bytes。 #### JVM 中两百万个字符串的总内存占用 1. **总内存开销**: - 如果没有字符串内部化或优化(比如字符串去重),每个字符串的存储开销为 40 bytes,两百万个字符串则需要:40 bytes×2,000,000=80,000,000 bytes40bytes×2,000,000=80,000,000bytes 2. **转换为 KB 和 MB**: - 80,000,000 bytes1024≈78,125 KB102480,000,000bytes​≈78,125KB - 80,000,000 bytes1024×1024≈76.294 MB1024×102480,000,000bytes​≈76.294MB #### 注意 - **字符串池**:在 Java 中,字符串字面量自动被内部化,存储在 JVM 的字符串池中。如果这些字符串是动态生成的并且不被显式地内部化(使用 `String.intern()`),则每个字符串都将占用独立的内存空间。如果使用字符串字面量或已内部化的字符串,那么内存占用可能会减少,因为多个字符串引用将指向内存中的同一对象。 - **压缩指针**:在较新的 JVM 实现中,如果堆大小小于 32GB,通常可以使用压缩指针,这可能减少对象引用所需的空间,从而略微降低每个字符串对象的内存占用。 总结来说,两百万个 "beijing_11352" 字符串在没有特别优化的情况下,大约需要 76.294 MB 的内存,这考虑了每个字符串实例和字符数组的存储需求。 - [ ] java 中的字符串为什么从 char 数组换成了 byte 数组 ⏰ 2024-04-30 📅 2024-04-30