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

10 篇文章 0 订阅
1 篇文章 0 订阅

有的地方要用一个简单的数组缓存运算结果,空间换时间,但是要求万一内存不够,要这些结果能被释放(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;
  }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值