哈希值可以简化对象的比较和查找操作,因为只需要比较哈希值即可确定对象是否相等。在Python中,只有不可变(immutable)的对象才能被哈希,比如整数、字符串和元组等。...if key in cache: print("从缓存中获取结果:", cache[key]) else: # 计算并缓存结果 result =...calculate_value(data) # 计算结果并缓存: 10data2 = {'value': 5}calculate_value(data2) # 从缓存中获取结果: 10在示例代码中,...为了避免字典作为键值导致的TypeError错误,我们将字典转换为元组并作为缓存字典的键。这样,即使字典的内容一样,但其对应的元组却不同,从而能够正确保存和获取缓存结果。...可变(mutable)对象: 可变对象是指它的值可以在创建之后被改变的对象。这意味着我们可以对可变对象进行添加、删除、更新操作,而其内存地址不会改变。
6 及之前 数据存储在 char[]数组中,String通过 offset 和 count两个属性定位 char[] 数据获取字符串。...,但字符串的值 value 仍然指向的是内存中的同一个数组,如下图所示: 如果我们仅仅是用 substring 获取一小段字符,而原始 string字符串非常大的情况下,substring 的对象如果一直被引用...高性能缓存 String不可变之后就能保证 hash值得唯一性,使得类似 HashMap容器才能实现相应的 key-value 缓存功能。 实现字符串常量池 由于不可变,才得以实现字符串常量池。...大字符串如何构建 既然 String 对象是不可变,所以我们在频繁拼接字符串的时候是否意味着创建多个对象呢?...总结与思考 我们从 String 进化历程掌握了她的组成,不断的改变成员变量节约内存。 她的不可变性从而实现了字符串常量池,减少同一个字符串的重复创建,节约内存。
来源 | 简书| 作者 | 指尖上的榴莲 一.原理(为什么说String类是不可变的) 1.什么是不可变对象 如果一个对象在创建之后就不能再改变它的状态,那么这个对象是不可变的(Immutable)。...3.允许String对象缓存hashcode 查看上文JDK1.8中String类源码,可以发现其中有一个字段hash,String类的不可变性保证了hashcode的唯一性,所以可以用hash字段对String...对象的hashcode进行缓存,就不需要每次重新计算hashcode。...所以Java中String对象经常被用来作为HashMap等容器的键。 4.安全性 如果String对象是可变的,那么会引起很严重的安全问题。...因为String对象是不可变的,所以它的值是不可改变的,否则黑客们可以钻到空子,改变String引用指向的对象的值,造成安全漏洞。
从打印结果可以看出,s的值确实改变了。那么怎么还说String对象是不可变的呢? 其实这里存在一个误区: s只是一个String对象的引用,并不是对象本身。...为什么String对象是不可变的? 要理解String的不可变性,首先看一下String类中都有哪些成员变量。..., 在Java中String类其实就是对字符数组的封装。...除此之外还有一个hash成员变量,是该String对象的哈希值的缓存,这个成员变量也和本文的讨论无关。在Java中,数组也是对象。 所以value也只是一个引用,它指向一个真正的数组对象。...但是一般我们不这么做。这个反射的实例还可以说明一个问题:如果一个对象,他组合的其他对象的状态是可以改变的,那么这个对象很可能不是不可变对象。
线程安全需同时考虑原子性和可见性问题,所以网上常说的不可变对象是线程安全的,其实是不严谨的。...通常为了保证缓存不被污染,当我们从缓存中提取对象时,会返回原始缓存对象的一个深拷贝,这样无论上层业务代码对提取到的对象如何修改,均不会对缓存本身造成影响。...2.2.3 更好的可维护性 当我们在代码中看到一个不可变对象时,心情是轻松的,因为这类对象很单纯,不会在哪个隐藏的逻辑分支中偷偷改变自身的状态,对代码的测试、调试和阅读理解都有好处。...不可变对象对并发编程友好、易于在进程内缓存、且拥有更好的可维护性,建议在自己能力范围内,尽量优先考虑使用不可变对象的设计。...比如颜色数值和颜色名可以因为多线程的调动而对应不上。 3.2定义不可变对象的策略 以下的一些规则是创建不可变对象的简单策略。
从打印结果可以看出,s的值确实改变了。那么怎么还说String对象是不可变的呢?其实这里存在一个误区:s只是一个String对象的引用,并不是对象本身。...为什么String对象是不可变的? 要理解String的不可变性,首先看一下String类中都有哪些成员变量。..., 在Java中String类其实就是对字符数组的封装。...除此之外还有一个hash成员变量,是该String对象的哈希值的缓存,这个成员变量也和本文的讨论无关。在Java中,数组也是对象(可以参考我之前的文章 java中数组的特性)。...但是一般我们不这么做。这个反射的实例还可以说明一个问题:如果一个对象,他组合的其他对象的状态是可以改变的,那么这个对象很可能不是不可变对象。
但一些面试者可能可以给出答案,“HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。...这一点有助于理解获取对象的逻辑。如果你没有意识到这一点,或者错误的认为仅仅只在 bucket中存储值的话,你将不会回答如何从HashMap中获取对象的逻辑。...因为HashMap使 用链表存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在链表中。”...不可变性使得能够缓存不同键的hashcode,这将提高整个获取对象的速度,使用 String,Interger这样的wrapper类作为键是非常好的选择。...不 可变性还有其他的优点如线程安全。如果你可以仅仅通过将某个field声明成final就能保证hashCode是不变的,那么请这么做吧。
jvm的对象,要特别注意对象中的共享状态 Shared:共享的 Mutable:可变的 当设计线程安全的类时,良好的面向对象技术、不可修改性,以及明晰的不变性规范都能起到一定的帮助作用; 无状态对象是线程安全的...:没有任何域也不包含任何对其他类中域的引用(比如StatelessFactory implements Servlet),多个线程访问并没有共享状态,不会影响其正确性。...volatile变量不会被缓存到寄存器或者对其他处理器不可见的地方,因此在读取volatile变量时总会返回最新写入的值。 volatile的一个用法:while的条件变量,为保证可见性。...volatile变量不会被缓存到寄存器或者对其他处理器不可见的地方,因此在读取volatile变量时总会返回最新写入的值。...构造函数中的对象是this,其他譬如引用类属性的拥有者为this,如果将这哥匿名类传递给source,source如果对其进行了引用,而这时候构造函数还没结束即没有创建ThisEscape的对象,这个匿名类也还没构造
有粉丝去阿里面试,跟码哥分享了其中一题面试问题「如何将重复性比较高的 String 类型的地址信息从 20GB 降到几百兆?」。 今天,码哥从多个角度带你完全攻克这个知识点,让面试官眼前一亮。...[]数组中,String通过 offset 和 count两个属性定位 char[] 数据获取字符串。...,但字符串的值 value 仍然指向的是内存中的同一个数组,如下图所示: 如果我们仅仅是用 substring 获取一小段字符,而原始 string字符串非常大的情况下,substring 的对象如果一直被引用...高性能缓存 String不可变之后就能保证 hash值得唯一性,使得类似 HashMap容器才能实现相应的 key-value 缓存功能。 实现字符串常量池 由于不可变,才得以实现字符串常量池。...大量字符串拼接对象如何优化 既然 String 对象是不可变,所以我们在频繁拼接字符串的时候是否意味着创建多个对象呢?
享元模式原理与实现 享元模式(Flyweight Design Pattern) 所谓“享元”,顾名思义就是被共享的单元。享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象。...具体来讲,当一个系统中存在大量重复对象的时候,如果这些重复的对象是不可变对象,我们就可以利用享元模式将对象设计成享元,在内存中只保留一份实例,供多处代码引用。...这里我稍微解释一下,定义中的“不可变对象”指的是,一旦通过构造函数初始化完成之后,它的状态(对象的成员变量或者属性)就不会再被修改了。所以,不可变对象不能暴露任何 set() 等修改内部状态的方法。...之所以要求享元是不可变对象,那是因为它会被多处代码共享使用,避免一处代码对享元进行了修改,影响到其他使用它的代码。 接下来,我们通过一个简单的例子解释一下享元模式。...享元模式 VS 单例、缓存、对象池 我们前面也多次提到,区别两种设计模式,不能光看代码实现,而是要看设计意图,也就是要解决的问题。这里的区别也不例外。我们可以用简单几句话来概括一下它们之间的区别。
在 Java6 以及之前的版本中 String对象是对 char 数组进行了封装实现的对象,主要有四个成员变量: char 数组、偏移量 offset、字符数量 count、哈希值 hash。...String对象是通过 offset 和 count 两个属性来定位 char[] 数组,获取字符串。这么做可以高效、快速地共享数组对象,同时节省内存空间,但这种方式很有可能会导致内存泄漏。 2....从 Java7 版本开始到 Java8 版本 从 Java7 版本开始,Java 对String类做了一些改变。String类中不再有 offset 和 count 两个变量了。...String 对象的不可变性 从我们知道String对象的那一刻起,我想大家都知道了String对象是不可变的。那它不可变是怎么做到的呢?Java 这么做能带来哪些好处?...假设 String 对象是可变的,那么 String 对象将可能被恶意修改。
也就是说,文件并没有被复制到内存缓存或数组中。相反,操作系统仅仅为文件内容保留了一段虚拟内存。当访问文件的不同区域时,这些区域的内容才根据需要被读取并映射到内存区域中。...—-mmap是什么 mmap是一种虚拟内存映射文件的方法,它可以将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对应关系。...对象是可变的,而 str 对象是不可变的 mmap 对象同时对应于打开的文件,多态于一个Python file 对象 mmap 对象可以切片和索引,也可以为它的切片或索引赋值(因为 mmap 对象是可变的...([offset, n]) 把 m 中从offset开始的n个字节刷到对应的文件中,参数 offset 要么同时指定,要么同时不指定; m.move(dstoff, srcoff, n) 等于...m.read(n) 返回一个字符串,从 m 对应的文件中最多读取 n 个字节,将会把 m 对应文件的位置指针向后移动; m.read_byte() 返回一个1字节长的字符串,从 m 对应的文件中读
工作内存里的变量,在多核处理器下,将大部分储存于处理器高速缓存中。 工作内存会拷贝主存中的变量,然后对变量的操作在自己的工作内存中进行。 线程之间无法相互直接访问,变量传递均需要通过主存完成。...如何保证内存计算一致性 1、缓存一致性 当一个线程更新了自己工作内存中的数据后,没有写到主内存,其他线程是不知道的。...a、获取对象监视器的锁(lock) b、清空工作内存数据, 从主存复制变量到当前工作内存, 即同步数据 (read and load) c、 执行代码,改变共享变量值 (use and...---- 线程安全模式 线程安全性的定义要求无论是多线程中的时序或交替操作,都要保证不破坏业务本身不变约束 。 为了保护状态的一致性,要在单一的原子操作中更新相互关联的状态变量。...状态和值对象 值对象是DDD中一种模型,不可变性。 状态是表达一段时间内一个逻辑为真的事实,状态是不可变的,因为我们不能回到过去改变状态。 状态是一种值对象。
但一些面试者可能可以给出答案,“HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。...这一点有助于理解获取对象的逻辑。如果你没有意识到这一点,或者错误的认为仅仅只在bucket中存储值的话,你将不会回答如何从HashMap中获取对象的逻辑。...因为HashMap使用链表存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在链表中。”...不可变性使得能够缓存不同键的hashcode,这将提高整个获取对象的速度,使用String,Interger这样的wrapper类作为键是非常好的选择。 ...我个人很喜欢这个问题,因为这个问题的深度和广度,也不直接的涉及到不同的概念。
多线程编程在Java中是一个常见的需求,它可以提高程序的性能和响应能力。然而,多线程编程也带来了一系列的线程安全与并发问题。...在多线程环境中,如果不采取适当的措施,可能会导致以下问题: 竞态条件(Race Condition):多个线程同时访问共享资源,竞争对资源的读写操作,导致数据不一致。...不可变对象(Immutable Objects) 不可变对象是指一旦创建,其状态不能被修改的对象。因为不可变对象的状态不可变,所以它们可以安全地在多个线程之间共享,而无需同步。...它具有以下特性: 当一个线程修改了volatile字段的值,其他线程会立即看到最新的值。 volatile字段不会被缓存在线程的本地内存中,而是直接从主内存中读取和写入。...为了避免死锁,可以采用以下方法: 按顺序获取锁:确保所有线程以相同的顺序获取锁,避免循环等待的情况。 使用tryLock:尝试获取锁一段时间,如果失败则释放已经获得的锁,然后重新尝试。
多线程编程在Java中是一个常见的需求,它可以提高程序的性能和响应能力。然而,多线程编程也带来了一系列的线程安全与并发问题。...在多线程环境中,如果不采取适当的措施,可能会导致以下问题: 竞态条件(Race Condition):多个线程同时访问共享资源,竞争对资源的读写操作,导致数据不一致。...不可变对象(Immutable Objects)不可变对象是指一旦创建,其状态不能被修改的对象。因为不可变对象的状态不可变,所以它们可以安全地在多个线程之间共享,而无需同步。...它具有以下特性:当一个线程修改了volatile字段的值,其他线程会立即看到最新的值。volatile字段不会被缓存在线程的本地内存中,而是直接从主内存中读取和写入。...为了避免死锁,可以采用以下方法: 按顺序获取锁:确保所有线程以相同的顺序获取锁,避免循环等待的情况。 使用tryLock:尝试获取锁一段时间,如果失败则释放已经获得的锁,然后重新尝试。
为什么说字符串是不可变的 在工作中,我们经常要在代码中对字符串进行赋值和改变它的值,但是,为什么我们说字符串是不可变的呢?...不可变对象是在完全创建后其内部状态保持不变的对象。这意味着,一旦对象被赋值给变量,我们既不能更新引用,也不能通过任何方式改变内部状态。...缓存 字符串是使用最广泛的数据结构。大量的字符串的创建是非常耗费资源的,所以,Java提供了对字符串的缓存功能,可以大大地节省堆空间。...性能 前面提到了的字符串池、hashcode缓存等,都是提升性能的提现。 因为字符串不可变,所以可以用字符串池缓存,可以大大节省堆内存。...而且还可以提前对hashcode进行缓存,更加高效 由于字符串是应用最广泛的数据结构,提高字符串的性能对提高整个应用程序的总体性能有相当大的影响。
因为HashMap的好处非常多,我曾经在电子商务的应用中使用HashMap作为缓存。...但其它线程可以通过set()方法更改集合对象是允许的,因为这并没有从“结构上”更改集合。...但一些面试者可能可以给出答案,“HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。...这一点有助于理解获取对象的逻辑。如果你没有意识到这一点,或者错误的认为仅仅只在bucket中存储值的话,你将不会回答如何从HashMap中获取对象的逻辑。...不可变性使得能够缓存不同键的hashcode,这将提高整个获取对象的速度,使用String,Interger这样的wrapper类作为键是非常好的选择。
领取专属 10元无门槛券
手把手带您无忧上云