java弱引用hashset和arraylist

工作中需要用到弱引用的集合和列表.网上搜集了点资料,自己整理下发出来备份.

WeakHashSet是模仿HashSet的实现方式,使用WeakHashMap实现的.

WeakArrayList是修改自org.arakhne.util.ref下的WeakArrayList.

SpeedyKit.copyOf方法是1.6中Arrays下同名方法.我用的1.5,需要把此方法拷贝出来.

 

import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import java.util.WeakHashMap;

/**
 * 参照{@link java.util.HashSet}实现的WeakHashSet.详细介绍参看{@link java.util.Set}和
 * {@link java.util.WeakHashMap}功能<br>
 * 
 */
public class WeakHashSet<E> extends AbstractSet<E> implements Set<E> {

	private transient WeakHashMap<E, Object>	map;

	private static final Object					PRESENT	= new Object();

	public WeakHashSet() {
		this.map = new WeakHashMap<E, Object>();
	}

	public WeakHashSet(Collection<? extends E> c) {
		this.map = new WeakHashMap<E, Object>(Math.max(
				(int) (c.size() / .75f) + 1, 16));
		this.addAll(c);
	}

	public WeakHashSet(int initialCapacity, float loadFactor) {
		this.map = new WeakHashMap<E, Object>(initialCapacity, loadFactor);
	}

	public WeakHashSet(int initialCapacity) {
		this.map = new WeakHashMap<E, Object>(initialCapacity);
	}

	public Iterator<E> iterator() {
		return this.map.keySet().iterator();
	}

	public int size() {
		return this.map.size();
	}

	@Override
	public boolean isEmpty() {
		return this.map.isEmpty();
	}

	@Override
	public boolean contains(Object o) {
		return this.map.containsKey(o);
	}

	@Override
	public boolean add(E o) {
		return this.map.put(o, WeakHashSet.PRESENT) == null;
	}

	@Override
	public boolean remove(Object o) {
		return this.map.remove(o) == WeakHashSet.PRESENT;
	}

	@Override
	public void clear() {
		this.map.clear();
	}
}

 

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.AbstractList;
import java.util.Collection;

/**
 * 弱引用列表 <br>
 * 
 */
public class WeakArrayList<T> extends AbstractList<T> {
	private static final long					serialVersionUID	= 2601162363164961860L;
	private static final Object					NULL_VALUE			= new Object();
	private final transient ReferenceQueue<T>	queue;
	private Object[]							data;
	private int									size;
	private boolean								enquedElement;

	@SuppressWarnings("unchecked")
	private static <T> T maskNull(T value) {
		return (T) (value == null ? WeakArrayList.NULL_VALUE : value);
	}

	private static <T> T unmaskNull(T value) {
		return (value == WeakArrayList.NULL_VALUE ? null : value);
	}

	public WeakArrayList(int initialCapacity) {
		this.queue = new ReferenceQueue<T>();

		this.enquedElement = false;

		if (initialCapacity < 0) {
			throw new IllegalArgumentException("Illegal Capacity: "
					+ initialCapacity);
		}
		this.data = new Object[initialCapacity];
		this.size = 0;
	}

	public WeakArrayList() {
		this(10);
	}

	public WeakArrayList(Collection<? extends T> c) {
		this.queue = new ReferenceQueue<T>();

		this.enquedElement = false;

		this.data = new Object[c.size()];
		this.size = this.data.length;
		int i = 0;
		for (T t : c) {
			this.data[i] = this.createRef(t);
			++i;
		}
	}

	@SuppressWarnings("unchecked")
	public String toString() {
		StringBuffer buffer = new StringBuffer();

		for (int i = 0; i < this.size; ++i) {
			Object obj;
			Reference<T> ref = (Reference<T>) this.data[i];
			if (this.data[i] == null) {
				obj = null;
			} else {
				obj = ref.get();
			}
			buffer.append('{');
			buffer.append(obj == null ? null : obj.toString());
			buffer.append('}');
		}
		return buffer.toString();
	}

	@SuppressWarnings("unchecked")
	private Reference<T> createRef(T obj) {
		return new WeakReference(WeakArrayList.maskNull(obj), this.queue);
	}

	public void ensureCapacity(int minCapacity) {
		this.modCount += 1;
		int oldCapacity = this.data.length;
		if (minCapacity > oldCapacity) {
			Object[] oldData = this.data;
			int newCapacity = oldCapacity * 3 / 2 + 1;
			if (newCapacity < minCapacity) {
				newCapacity = minCapacity;
			}
			this.data = SpeedyKit.copyOf(oldData, newCapacity);
		}
	}

	public void trimToSize() {
		this.modCount += 1;
		int oldCapacity = this.data.length;
		if (this.size < oldCapacity) {
			this.data = SpeedyKit.copyOf(this.data, this.size);
		}
	}

	@SuppressWarnings("unchecked")
	public int expurge() {
		int j;
		while (this.queue.poll() != null) {
			this.enquedElement = true;
		}

		if (this.enquedElement) {
			j = 0;
			for (int i = 0; i < this.size; ++i) {
				Reference<T> ref = (Reference<T>) this.data[i];
				if (ref == null || ref.isEnqueued() || ref.get() == null) {
					if (ref != null) {
						ref.clear();
					}
					this.data[i] = null;
				} else {
					if (i != j) {
						this.data[j] = this.data[i];
						this.data[i] = null;
					}
					++j;
				}
			}
			this.enquedElement = false;
		} else {
			j = this.size;
		}

		while (this.queue.poll() != null) {
			this.enquedElement = true;
		}

		this.size = j;

		return this.size;
	}

	protected void assertRange(int index, boolean allowLast) {
		int csize = this.expurge();
		if (index < 0) {
			throw new IndexOutOfBoundsException("invalid negative value: "
					+ Integer.toString(index));
		}
		if (allowLast && index > csize) {
			throw new IndexOutOfBoundsException("index>" + csize + ": "
					+ Integer.toString(index));
		}
		if (!allowLast && index >= csize) {
			throw new IndexOutOfBoundsException("index>=" + csize + ": "
					+ Integer.toString(index));
		}
	}

	public int size() {
		return this.expurge();
	}

	@SuppressWarnings("unchecked")
	public T get(int index) {
		Object value;
		do {
			this.assertRange(index, false);
			value = ((Reference<T>) this.data[index]).get();
		} while (value == null);
		return (T) WeakArrayList.unmaskNull(value);
	}

	@SuppressWarnings("unchecked")
	public T set(int index, T element) {
		Object oldValue;
		Reference<T> ref;
		do {
			this.assertRange(index, false);
			ref = (Reference<T>) this.data[index];
			oldValue = ref.get();
		} while (oldValue == null);
		ref.clear();
		this.data[index] = this.createRef(element);
		this.modCount += 1;
		return (T) WeakArrayList.unmaskNull(oldValue);
	}

	public void add(int index, T element) {
		this.assertRange(index, true);
		this.ensureCapacity(this.size + 1);
		System.arraycopy(this.data, index, this.data, index + 1, this.size
				- index);
		this.data[index] = this.createRef(element);
		this.size += 1;
		this.modCount += 1;
	}

	@SuppressWarnings("unchecked")
	public T remove(int index) {
		Object oldValue;
		Reference<T> ref;
		do {
			this.assertRange(index, false);
			ref = (Reference<T>) this.data[index];
			oldValue = ref.get();
		} while (oldValue == null);
		ref.clear();
		System.arraycopy(this.data, index + 1, this.data, index, this.size
				- index - 1);
		this.data[(this.size - 1)] = null;
		this.size -= 1;
		this.modCount += 1;
		return (T) WeakArrayList.unmaskNull(oldValue);
	}

	public static void main(String[] args) {
		Object a = new Object();
		WeakArrayList<Object> list = new WeakArrayList<Object>();
		for (int i = 0; i < 100000; i++) {
			list.add(a);
		}
		int size = list.size();
		System.out.println(size);
		a = null;
		while (list.size() == size) {
			System.gc();
		}
		System.out.println(list.size());
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值