java 集合 标识散列映射 及相关知识与实例

来源:互联网 发布:网络神曲2016 编辑:程序博客网 时间:2024/06/05 01:17

类IdentityHashMap有特殊的作用,在这个类中,键的散列值不是用hashCode函数计算出来的,而是用System.identityHashCode方法计算出来的。这是Object.hashCode方法根据对象的内存地址来计算散列码时所使用的方式

            System.identityHashCodejava.lang 类 Systemjava.lang.Object  继承者 java.lang.System  identityHashCodepublic static int identityHashCode(Object x)返回给定对象的哈希码,该代码与默认的方法 hashCode() 返回的代码一样,无论给定对象的类是否重写 hashCode()。null 引用的哈希码为 0。参数:x - 要计算其哈希码的对象返回:哈希码//对比                    Object.hashCodejava.lang 类 Objectjava.lang.Objectpublic class Object类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。hashCodepublic int hashCode()返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。hashCode 的常规协定是:在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)返回:此对象的一个哈希码值。//对比                        类IdentityHashMapjava.util 类 IdentityHashMap<K,V>java.lang.Object  继承者 java.util.AbstractMap<K,V>      继承者 java.util.IdentityHashMap<K,V>此类利用哈希表实现 Map 接口,比较键(和值)时使用引用相等性代替对象相等性。换句话说,在 IdentityHashMap 中,当且仅当 (k1==k2) 时,才认为两个键 k1 和 k2 相等(在正常 Map 实现(如 HashMap)中,当且仅当满足下列条件时才认为两个键 k1 和 k2 相等:(k1==null ? k2==null : e1.equals(e2)))。此类不是 通用 Map 实现!此类实现 Map 接口时,它有意违反 Map 的常规协定,该协定在比较对象时强制使用 equals 方法。此类设计仅用于其中需要引用相等性语义的罕见情况。

注意,在对两个对象进行比较时,IdentityHashMap类使用==,而不是使用equals
也就是两个对象必须完全相等才相等,不同键的两个对象,即使内容相同,也被视为不同的对象。在实现对象遍历算法(如对象串行化)时候,这个类非常有用,可以用来跟踪每个对象的遍历情况(内容相同且地址相同)

java.util.WeakHashMap<K,V>    WeakHashMap();    WeakHashMap(int initialCapcity)    WeakHashMap(int initialCapcity,float loadFactor)    用给定的容量和填充因子构造一个空的散列映射表java.util.LinkedHashSet    LinkedHashSet();    LinkedHashSet(int initialCapcity)    LinkedHashSet(int initialCapcity,float loadFactor);    用给定的容量和填充因子构造一个空链接散列表LinkedHashMap和LinkedHashSet类用来记住插入元素项的顺序。这样就可以避免在散列表中的项从表面上看是随机的(用了LinkedHashMap,散列表中的项从表面上看就不随机了)当条目插入到表中时,就会并入到双向链表中。                        链接散列集与映射链接散列集将用访问顺序,而不是插入顺序,对连接条目进行迭代。每次调用get或者put,受到影响的条目将从当前的位置删除,并放到条目链表的尾部(只有条目在链表中的位置会受到影响,而散列表中的桶不会受到影响。一个条目总位于与散列码对应的桶中(链接散列集是桶外的链表)想构造这样的一个散列映射表,请调用LinkedHashMap<K,V>(initialCapacity,LoadFactor,true)访问顺序对于实现高速缓存的最近最少使用原则十分重要,例如,可能希望将访问的频率高的元素放在内存中,而访问频率低的元素则从数据库中读取。当在表中找不到元素项且表又已经满时,,可将迭代器加入到表中,将枚举的前几个元素删除,这些是近期最少使用的几个元素。总而言之:用一次,放到最后,不用的慢慢就会降到开头甚至可以让这一过程自动化。即构造一个LinkedHashMap子类,然后覆盖下面这个方法:protected boolean removeEldestEntry(Map.Entry<K,V> eldest)    每当方法返回true时候,就添加一个新条目,从而导致删除eldest条目。例如,下面的高速缓存可以存放100个元素:    Map<K,V>  cache =new  LinkedHashMap<>(128,0.75,true)    {        protected boolean removeEldestEntry(Map.Entry<K,V> eldest)        {            return size()>100;        }    }();
package NEW_DATE_SEQUENCE_PACKAGE;import java.util.HashMap;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.LinkedHashSet;import java.util.Map;import java.util.Set;/** * * @author cmx */public class J_9_1_2 {    public static void main(String[] args)    {        Map<String,Employee_61> staff=new HashMap<>();        staff.put("144-25", new Employee_61("well"));        staff.put("567-24", new Employee_61("hello"));        staff.put("157-62", new Employee_61("good"));        staff.put("456-62", new Employee_61("thanks"));        Iterator<String> a=staff.keySet().iterator();        while(a.hasNext())                System.out.println(a.next());         System.out.println("============");        Map<String,Employee_61> staff2=new LinkedHashMap<>();        staff2.put("144-25", new Employee_61("well"));        staff2.put("567-24", new Employee_61("hello"));        staff2.put("157-62", new Employee_61("good"));        staff2.put("456-62", new Employee_61("thanks"));        Iterator<String> a2=staff2.keySet().iterator();        while(a2.hasNext())                System.out.println(a2.next());        Map<String,Employee_62>  cache =new  LinkedHashMap<>(128,0.75,true)   //????????    {        public boolean removeEldestEntry(Map.Entry<String,Employee_62> eldest)        {            return size()>100;        }    };    }}class Employee_62 {    private String name;    public  Employee_62(String name)    {        this.name=name;    }    public String getName()    {        return name;    }}

另外,还可以对eldest条目进行评估,以此决定是否应该将他删除。例如,可以检查与这个条目一起存在的时间戳
时间戳(timestamp),一个能表示一份数据在某个特定时间之前已经存在的、 完整的、 可验证的数据,通常是一个字符序列,唯一地标识某一刻的时间。使用数字签名技术产生的数据, 签名的对象包括了原始文件信息、 签名参数、 签名时间等信息。广泛的运用在知识产权保护、 合同签字、 金融帐务、 电子报价投标、 股票交易等方面。

LinkedHashSet<String,Employee_61> staff2=new LinkedHashSet<>();//是不对的,因为Class LinkedHashSet<E>,而不是LinkedHashSet<K,V>
java.util.LinkedHashMap<K,V>    LinkedHashMap()    LinkedHashMap(int initialCapcity)    LinkedHashMap(int initialCapcity,float loadFactor)    LinkedHashMap(int initialCapcity,float loadFactor,boolean accessOrder);    用给定的容量,填充因子,和顺序构造一个空的链接散列映射表。    accessOrder参数为true时表示访问顺序,为false时候,表示插入顺序    protected boolean removeEldestEntry(Map.Entry<K,V> eldest)