这种方法HashCode的计算方法可能最早出现在Brian W. Kernighan和Dennis M. Ritchie的《The C Programming Language》中,被认为是性价比最高的算法(又被称为times33算法,因为C中乘数常量为33,JAVA中改为31),实际上,包括List在内的大多数的对象都是用这种方法计算Hash值。
遍历HashMap所得到的数据是杂乱无章的,这在某些情况下客户需要特定遍历顺序时是十分有用的。比如,这种数据结构很适合构建 LRU 缓存。调用 put 或 get 方法将会访问相应的条目(假定调用完成后它还存在)。putAll 方法以指定映射的条目集合迭代器提供的键-值映射关系的顺序,为指定映射的每个映射关系生成一个条目访问。Sun提供的J2SE说明文档特别规定任何其他方法均不生成条目访问,尤其,collection 集合类的操作不会影响底层映射的迭代顺序。
上述代码输出一次Checking for empty就退出了主线程,意味着GC在最近的一次垃圾回收周期中清除了new String(“Alibaba”),同时WeakHashMap也做出了及时的反应,将该键对应的条目删除了。如果将map的类型改为HashMap的话,由于其内部采用的是强引用机制,因此即使GC被显示调用,map中的条目依然存在,程序会不断地打出Checking for empty字样。另外,在使用WeakHashMap的情况下,若是将
Java代码
map.put(new String("Alibaba"), "alibaba");
改为
Java代码
map.put("Alibaba", "alibaba");
程序还是会不断输出Checking for empty。这与前面我们分析的WeakHashMap的弱引用机制并不矛盾,因为JVM为了减小重复创建和维护多个相同String的开销,其内部采用了蝇量模式(《JAVA与模式》),此时的“Alibaba”是存放在常量池而非堆中的,因此即使没有对象指向“Alibaba”,它也不会被GC回收。弱引用特别适合以下对象:占用大量内存,但通过垃圾回收功能回收以后很容易重新创建。
Shallow size of an object is the amount of memory allocated to store the object itself, not taking into account the referenced objects. Shallow size of a regular (non-array) object depends on the number and types of its fields. Shallow size of an array depends on the array length and the type of its elements (objects, primitive types). Shallow size of a set of objects represents the sum of shallow sizes of all objects in the set.
Retained size of an object is its shallow size plus the shallow sizes of the objects that are accessible, directly or indirectly, only from this object. In other words, the retained size represents the amount of memory that will be freed by the garbage collector when this object is collected.
To better understand the notion of the retained size, let us look at the following examples:
In order to measure the retained sizes, all objects in memory are treated as nodes of a graph where its edges represent references from objects to objects. There are also special nodes - GC root objects, which will not be collected by Garbage Collector at the time of measuring (read more about GC roots).
The pictures below show the same set of objects, but with varying internal references.
Figure 1:
Figure 2:
Let us consider obj1. As you can see, in both pictures we have highlighted all of the objects that are directly or indirectly accessed only by obj1. If you look at Figure 1, you will see thatobj3 is not highlighted, because it is also referenced by a GC root object. On Figure 2, however, it is already included into the retained set, unlike obj5, which is still referenced by GC root.
Thus, the retained size of obj1 will represent the following respective values:
For Figure 1: the sum of shallow sizes of obj1, obj2 and obj4
For Figure 2: the sum of shallow sizes of obj1, obj2, obj3 and obj4
Looking at obj2, however, we see that its retained size in the above cases will be:
For Figure 1: the sum of shallow sizes of obj2 and obj4
For Figure 2: the sum of shallow sizes of obj2, obj3 and obj4
In general, retained size is an integral measure, which helps to understand the structure (clustering) of memory and the dependencies between object subgraphs, as well as find potential roots of those subgraphs.