您的位置:首页 > 编程语言 > Java开发

Java工具: 一个类型安全的 WeakArray

2012-10-02 09:20 267 查看
有的地方要用一个简单的数组缓存运算结果,空间换时间,但是要求万一内存不够,要这些结果能被释放(WeakReference),所以有了这个工具类。

/*
* Copyright 2012 raistlic (raistlic@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.lang.ref.WeakReference;
import java.util.Iterator;

/**
* This class simply encapsulates an array to be used as a cache, which holds
* weak references.
*
* It is intended to store "not so important" contents, which can be GCed
* when required.
*
* The iterator of this class can be used to iterate it, or remove elements
* from it, removing elements using the iterator will not effect the subsequent
* elements' positions.
*
* @author raistlic
* @date   27/09/2012
*/
public class WeakArray<E> implements Iterable<E> {

@SuppressWarnings({"unchecked", "rawtypes"})
private WeakReference<E>[] data;
public WeakArray(int size) {

if( size < 0 )
throw new IllegalArgumentException("Invalid array size: " + size);

data = (WeakReference<E>[])new WeakReference[size];
}

public int length() {

return data.length;
}

public void set(int index, E element) {

// potentially throws ArrayIndexOutOfBoundsException
if( get(index) != element )
data[index] = new WeakReference<E>(element);
}

public E get(int index) {

// potentially throws ArrayIndexOutOfBoundsException
WeakReference<E> ref = data[index];
return ref == null ? null : ref.get();
}

public void remove(int index) {

// potentially throws ArrayIndexOutOfBoundsException
data[index] = null;
}

@Override
public Iterator<E> iterator() {

return new IndexIterator();
}

private class IndexIterator implements Iterator<E> {

private int index = 0;

@Override
public boolean hasNext() {

return index < length();
}

@Override
public E next() {

// potentially throws ArrayIndexOutOfBoundsException
E result = get(index);
index++;
return result;
}

@Override
public void remove() {

// potentially throws ArrayIndexOutOfBoundsException
WeakArray.this.remove(index);
index++;
}
}
}


上一篇文章里用来计算阶乘的工具类 Calculator,可以使用 WeakArray 来cache运算结果,修改如下:

/*
* Copyright 2012 raistlic (raistlic@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.math.BigInteger;

/**
* This class is intended to provide convenient facilities for
* frequently used maths calculations that {@code java.lang.Math}
* does not cover.
*
* @date   08/08/2012
* @author raistlic
*/
public final class Calculator {

private Calculator() {}

private static final WeakArray<BigInteger> FACT_POOL =
new WeakArray<BigInteger>(1024);
public static BigInteger factorial(int number) {

if( number < 0 )
throw new IllegalArgumentException();

BigInteger result = null;

if( number < FACT_POOL.length() )
result = FACT_POOL.get(number);

if( result == null ) {

int lastCachedIndex = lastCachedFactIndex(number);
if( lastCachedIndex > 0 )
result = FACT_POOL.get(lastCachedIndex);
if( result == null )
result = BigInteger.ONE;

for(int i = Math.max(2, lastCachedIndex+1); i <= number; i++) {

result = result.multiply(BigInteger.valueOf(i));
if( i < FACT_POOL.length() )
FACT_POOL.set(i, result);
}
}
return result;
}

private static int lastCachedFactIndex(int number) {

for(int i=Math.min(number, FACT_POOL.length()-1); i>=0; i--) {

if( FACT_POOL.get(i) != null )
return i;
}

return -1;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: