软引用类似于可有可物的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会在引发“内存不足”异常前先回收这些对象的内存。软引用可用来实现内存敏感的高速缓存。
Java自带了一个 WeakHashMap 类用以实现弱引用,自带一个 SoftCache 类用以实现软引用缓存,以下给出自定义的软引用类的源码。
package com.ffcs.ods.common.util; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import java.util.Set; /** * @版权:福富软件 版权所有 (c) * @文件:com.ffcs.ods.common.util.SoftHashMap.java * @author: g.yanjj * @see: Map, HashMap, WeakHashMap, SoftCache * @创建日期: * @功能说明:具有软引用特性的哈希表,可用于存放缓存数据 * @修改记录: */ public class SoftHashMap<K,V> implements Map<K,V> { /** * 用来存放软引用的内部Map */ private final Map<K, SoftReferValue<K,V>> hash = new HashMap<K, SoftReferValue<K,V>>(); /** * 用来存放已被清除的软引用对象 */ private ReferenceQueue<V> queue = new ReferenceQueue<V>(); /** * 需要保留最近使用的缓存的数量,为0则代表不用特意保留缓存 */ private final int HARD_SIZE; /** * 用来保留最近使用的缓存的FIFO链表,将最近使用过的缓存存入链首 */ private final LinkedList<V> hardCache = new LinkedList<V>(); /** * 具有软引用特性的哈希表 */ public SoftHashMap() { HARD_SIZE = 0; } /** * 具有软引用特性的哈希表 * * @param keepSize 指定最多需要保留的最近使用过的缓存数量 */ public SoftHashMap(int keepSize) { HARD_SIZE = keepSize; } /** * 清除所有的键值对,执行后哈希表为空。 */ @Override public void clear() { hardCache.clear(); clearReferQueue(); hash.clear(); } /** * 判断哈希表是否包含指定的键 * * @param key 要判断的键对象,键对象为null时一定返回false。 * @return <tt>true</tt> 包含指定键,<tt>false</tt> 不包含指定键。 */ @Override public boolean containsKey(Object key) { if (null != key){ clearReferQueue(); return hash.containsKey(key); } else { return false; } } /** * 判断哈希表是否包含有指定的值 * * @param value 要判断的值对象,值对象为null时一定返回false。 * @return <tt>true</tt> 包含指定值,<tt>false</tt> 不包含指定值。 */ @Override public boolean containsValue(Object value) { if (null != value) { clearReferQueue(); for (SoftReferValue<K,V> srv : hash.values()) { if (value.equals(srv.get())) { return true; } } } return false; } /** * SoftHashMap类并没有使用内部集,因此此方法会抛出一个异常 * * @return 不会返回任何对象,抛出异常 * @exception UnsupportedOperationException */ @Override public Set<Map.Entry<K,V>> entrySet() { //没有内部集合类 throw new UnsupportedOperationException(); } /** * 根据键对象,获取值对象。 * * <p>由于值对象可能会被回收,此方法只会返回键存在,并且未被回收的值对象。 * * <p>如果在构造函数中指定了“缓存保留数”,则最近获取的“缓存保留数”个数的值对象将不会被回收。 * * @param key 要用于取值的键对象 * @return 返回对应的未被回收的值对象,如果键不存在或值对象已被回收,则返回{@code null} */ @Override public V get(Object key) { V result = null; //根据键获取值的引用 SoftReferValue<K,V> valueRef = hash.get(key); if (null != valueRef) { //软引用所指向的对象有可能已被回收,因此需要判断目标对象是否为空 result = valueRef.get(); if (null == result) { //如果目标对象已被回收,则从哈希表中移除这个无效键值对 hash.remove(key); clearReferQueue(); } else { //如果需要保留最近使用的缓存,则将目标对象推入强引用链表 if (HARD_SIZE > 0) { hardCache.addFirst(result); if (hardCache.size() > HARD_SIZE) { hardCache.removeLast(); } } } } return result; } /** * 判断哈希表是否是空的 * * @return <tt>true</tt>哈希表没有任何键值对,<tt>false</tt>哈希表至少有一个键值对。 */ @Override public boolean isEmpty() { return size() == 0; } /** * 返回哈希表的键对象的集合 */ @Override public Set<K> keySet() { return hash.keySet(); } /** * 将键值对添加到哈希表 * * @param key 键对象类似一个索引,可用于查找值对象 * @param value 值对象是保存实际数据的对象,可通过键对象查找 * @return 如果该键对象之前已在哈希表中存在,则返回原有的值对象。 * 如果返回{@code null},可能是该键对象第一次添加到哈希表,或原先存放的值对象为null,或原先存放的值对象已被回收。 */ @Override public V put(K key, V value) { clearReferQueue(); SoftReferValue<K,V> srv = new SoftReferValue<K,V>(value, key, queue); srv = hash.put(key, srv); if (null == srv){ return null; } else { return srv.get(); } } /** * 将指定Map中的键值对,批量添加到哈希表 * * @param m 要添加到哈希表的源表 */ @Override public void putAll(Map<? extends K, ? extends V> m) { for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) { Map.Entry<? extends K, ? extends V> e = i.next(); hash.put(e.getKey(), new SoftReferValue<K,V>(e.getValue(), e.getKey(), queue)); } } /** * 根据指定键,从哈希表移除对应的键值对 * * @param key 要移除的键 * @return 返回被移除的值对象,如果哈希表不存在指定键则返回{@code null} */ @Override public V remove(Object key) { clearReferQueue(); SoftReferValue<K,V> srv = hash.remove(key); if (null == srv){ return null; } else { return srv.get(); } } /** * 返回哈希表有效的键值对数量,在返回之前,已被回收的值对象将被移除 * * @return 哈希表有效的键值对数量 */ @Override public int size() { clearReferQueue(); return hash.size(); } /** * SoftHashMap类不支持返回值对象集合,此方法会抛出一个异常 * * @return 不会返回任何对象,抛出异常 * @exception UnsupportedOperationException */ @Override public Collection<V> values() { //不支持获取软引用集合 throw new UnsupportedOperationException(); } /** * 继承的软引用内部类,加入key属性是为了方便从值对象查找对应的键 */ private static class SoftReferValue<K,V> extends SoftReference<V> { private final K key; private SoftReferValue(V value, K key, ReferenceQueue<V> queue) { super(value, queue); this.key = key; } } /** * 清空引用队列,清除已被回收的软引用对象 */ private void clearReferQueue() { SoftReferValue<K,V> srv; while ((srv = (SoftReferValue<K,V>) queue.poll()) != null) { hash.remove(srv.key); } } }
相关推荐
哈希表的建立和查找哈希表的建立和查找哈希表的建立和查找哈希表的建立和查找
对一批关键字集合采用开放定址哈希表的存储结构来建立相应的哈希表和完成查找过程。 (1) 熟练掌握哈希表的构造方法 (2) 理解哈希表与其他结构表的实质性差别。
1、 哈希表类的哈希函数采用除留余数法哈希函数; 2、 解决哈希冲突的函数采用开放定址法中的线性探察法。 3、 建立一个由10个数据元素组成的集合; 4、 测试哈希表长度m=13和m=11两种情况下的哈希表,并查找其中的...
////采用除留余数法定义哈希表,哈希表长度为10,哈希函数为H(key)=key%13。产生冲突时采用线性探测法实现下面要求的功能。 ////(1)初始化哈希表,置空哈希表 ////(2)在哈希表中查找元素 ////(3)在哈希表中...
哈希表课程设计数据结构实验报告——哈希表设计 针对某个集体中的人名设计一个哈希表,使得平均查找长度不超过R,完成相应的建立和查表程序. 1.2 人名为汉语拼音形式,最长不超过18个字符(如:庄双双 ...
/为班级30个人的姓名设计一个哈希表,假设姓名用汉语拼音表示。要求用除留余数法 构造哈希函数,用线性探测再散列法处理冲突,平均查找长度的上限为2。 编写数据结构和算法来实现。要求:将哈希函数和处理冲突方法...
哈希表设计程序设计+数据结构实验报告 1.1 针对某个集体中的人名设计一个哈希表,使得平均查找长度不超过R,完成相应的建立和查表程序. 1.2 人名为汉语拼音形式,最长不超过18个字符(如:庄双双 zhuangshuangshuang)...
哈希表的概念作用及意义,哈希表的构造方法
哈希表应用 设计哈希表实现图书查找系统,完成相应的建表和查表程序。从键盘输入各图书相关信息,分别以图书编号为关键字建立散列表。待填入哈希表的书号至少30个;构造合适的哈希函数。 (1)记录由外部输入。 (2...
简单哈希表模型。可以助你更好的完成哈希表相关的编程。
public成员包括构造函数、析构函数和复制构造函数以及=重载函数,其它成员函数主要有:traver(遍历散列表)、show()(打印出哈希表所存的元素)返回值为bool类型的函数search\insert\Delete。search函数(查询关键字为...
用C语言实现的哈希表设计,内有姓名列表,只要输入姓名就可得到查到在哈希表中的相应位置
鱼刺线程池例程 哈希表 标签反馈 多线程示例。模块:。哈希表asm 哈希表类_汇编版(HashMap_ASM) 支持自定义数据值。@skychat。
哈希表的设计与实现课程设计 问题描述:针对某个单位电话号码簿,设计一个哈希表,并完成相应的建表和查表程序。 基本要求:设每个记录有下列数据项:电话号码、用户名、住址。从键盘输入各记录,以用户名为关键字...
石家庄铁道大学 刘立嘉 算法与数据结构 实验五 哈希表设计
假设人名为中国人姓名的汉语拼音形式。待填入哈希表的人名共有30个,取平均查找长度的上限为2。哈希函数用除留余数法构造,用线性探测再散列法或链地址法处理冲突。
问题描述:针对某个单位电话号码簿,设计一个哈希表,并完成相应的建表和查表程序。 基本要求:设每个记录有下列数据项:电话号码、用户名、住址。从键盘输入各记录,以用户名为关键字建立哈希表,哈希函数用除留取...
初始化哈希表 清空哈希表 哈希函数 在哈希表中查找元素 在哈希表中插入一个元素 输出哈希表中所有元素
哈希表的设计与实现哈希表的设计与实现哈希表的设计与实现
哈希表--链表 哈希表--链表 哈希表--链表 哈希表--链表哈希表--链表 哈希表--链表哈希表--链表 哈希表--链表哈希表--链表 哈希表--链表哈希表--链表 哈希表--链表