Java Tutorial/Collections/Reference

Материал из Java эксперт
Перейти к: навигация, поиск

An implementation of Set that manages a map of soft references to the set values.

   <source lang="java">

/*

* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.reflect.Array; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Set; /**

* An implementation of Set that manages a map of soft references to the set
* values. The map is keyed by the value hashCode and so this is only useful for
* value whose hashCode is a valid identity representation (String, primative
* wrappers, etc).
* 
* @author Scott.Stark@jboss.org
* @version $Revision: 2787 $
*/

@SuppressWarnings("unchecked") public class SoftSet implements Set {

 private HashMap map = new HashMap();
 /** The queue of garbage collected soft references */
 private ReferenceQueue gcqueue = new ReferenceQueue();
 static class ComparableSoftReference extends SoftReference {
   private Integer key;
   ComparableSoftReference(Integer key, Object o, ReferenceQueue q) {
     super(o, q);
     this.key = key;
   }
   Integer getKey() {
     return key;
   }
 }
 static class ComparableSoftReferenceIterator implements Iterator {
   Iterator theIter;
   ComparableSoftReferenceIterator(Iterator theIter) {
     this.theIter = theIter;
   }
   public boolean hasNext() {
     return theIter.hasNext();
   }
   public Object next() {
     ComparableSoftReference csr = (ComparableSoftReference) theIter.next();
     return csr.get();
   }
   public void remove() {
     theIter.remove();
   }
 }
 /**
  * 
  */
 public SoftSet() {
 }
 public int size() {
   processQueue();
   return map.size();
 }
 public boolean isEmpty() {
   processQueue();
   return map.isEmpty();
 }
 public boolean contains(Object o) {
   processQueue();
   Integer key = new Integer(o.hashCode());
   boolean contains = map.containsKey(key);
   return contains;
 }
 public Iterator iterator() {
   processQueue();
   Iterator theIter = map.values().iterator();
   return new ComparableSoftReferenceIterator(theIter);
 }
 public Object[] toArray() {
   processQueue();
   return toArray(new Object[0]);
 }
 public Object[] toArray(Object[] a) {
   processQueue();
   int size = map.size();
   Object[] array = {};
   if (a.length >= size)
     array = a;
   Iterator iter = map.values().iterator();
   int index = 0;
   while (iter.hasNext()) {
     ComparableSoftReference csr = (ComparableSoftReference) iter.next();
     Object value = csr.get();
     // Create the correct array type
     if (array.length == 0) {
       if (value == null) {
         index++;
         continue;
       }
       Array.newInstance(value.getClass(), size);
     }
     array[index] = value;
     index++;
   }
   return array;
 }
 public boolean add(Object o) {
   processQueue();
   Integer key = new Integer(o.hashCode());
   ComparableSoftReference sr = new ComparableSoftReference(key, o, gcqueue);
   return map.put(key, sr) == null;
 }
 public boolean remove(Object o) {
   processQueue();
   Integer key = new Integer(o.hashCode());
   return map.remove(key) != null;
 }
 public boolean containsAll(Collection c) {
   processQueue();
   Iterator iter = c.iterator();
   boolean contains = true;
   while (iter.hasNext()) {
     Object value = iter.next();
     Integer key = new Integer(value.hashCode());
     contains &= map.containsKey(key);
   }
   return contains;
 }
 public boolean addAll(Collection c) {
   processQueue();
   Iterator iter = c.iterator();
   boolean added = false;
   while (iter.hasNext()) {
     Object value = iter.next();
     Integer key = new Integer(value.hashCode());
     ComparableSoftReference sr = new ComparableSoftReference(key, value, gcqueue);
     added |= map.put(key, sr) == null;
   }
   return added;
 }
 public boolean retainAll(Collection c) {
   Iterator iter = iterator();
   boolean removed = false;
   while (iter.hasNext()) {
     Object value = iter.next();
     if (c.contains(value) == false) {
       iter.remove();
       removed = true;
     }
   }
   return removed;
 }
 public boolean removeAll(Collection c) {
   processQueue();
   Iterator iter = c.iterator();
   boolean removed = false;
   while (iter.hasNext()) {
     Object value = iter.next();
     removed |= remove(value);
   }
   return removed;
 }
 public void clear() {
   while (gcqueue.poll() != null)
     ;
   map.clear();
 }
 public boolean equals(Object o) {
   return map.equals(o);
 }
 public int hashCode() {
   return map.hashCode();
 }
 /**
  * Iterate through the gcqueue for for any cleared reference, remove the
  * associated value from the underlying set.
  */
 private void processQueue() {
   ComparableSoftReference cr;
   while ((cr = (ComparableSoftReference) gcqueue.poll()) != null) {
     map.remove(cr.getKey());
   }
 }

}</source>





Cache based on SoftReference

   <source lang="java">

/* Copyright 2004 The Apache Software Foundation

*
*   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.
*/

// Revised from xmlbeans import java.util.HashMap; import java.lang.ref.SoftReference; /**

* @author Cezar Andrei (cezar.andrei at bea.ru)
*         Date: Apr 26, 2005
*/

public class SoftCache {

   private HashMap map = new HashMap();
   public Object get(Object key)
   {
       SoftReference softRef = (SoftReference)map.get(key);
       if (softRef==null)
           return null;
       return softRef.get();
   }
   public Object put(Object key, Object value)
   {
       SoftReference softRef = (SoftReference)map.put(key, new SoftReference(value));
       if (softRef==null)
           return null;
       Object oldValue = softRef.get();
       softRef.clear();
       return oldValue;
   }
   public Object remove(Object key)
   {
       SoftReference softRef = (SoftReference)map.remove(key);
       if (softRef==null)
           return null;
       Object oldValue = softRef.get();
       softRef.clear();
       return oldValue;
   }

}</source>





WeakReference list uses java.lang.ref.WeakReferences to store its contents.

   <source lang="java">

/**

* 
* JFreeReport : a free Java reporting library
* 
*
* Project Info:  http://reporting.pentaho.org/
*
* (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ------------
* WeakReferenceList.java
* ------------
* (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
*/

import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; import java.lang.ref.Reference; import java.lang.ref.WeakReference; /**

* The WeakReference list uses java.lang.ref.WeakReferences to store its contents. In contrast to the
* WeakHashtable, this list knows how to restore missing content, so that garbage collected elements can be restored
* when they are accessed.
* <p/>
* By default this list can contain 25 elements, where the first element is stored using a strong reference, which is
* not garbage collected.
* <p/>
* Restoring the elements is not implemented, concrete implementations will have to override the
* restoreChild(int) method. The getMaxChildCount method defines the maxmimum number of
* children in the list. When more than maxChildCount elements are contained in this list, add will always
* return false to indicate that adding the element failed.
* <p/>
* To customize the list, override createReference to create a different kind of reference.
* <p/>
* This list is able to add or replace elements, but inserting or removing of elements is not possible.
*
* @author Thomas Morgner
*/

public abstract class WeakReferenceList implements Serializable, Cloneable {

 /**
  * The master element.
  */
 private Object master;
 /**
  * Storage for the references.
  */
 private transient Reference[] childs;
 /**
  * The current number of elements.
  */
 private int size;
 /**
  * The maximum number of elements.
  */
 private final int maxChilds;
 /**
  * Creates a new weak reference list. The storage of the list is limited to getMaxChildCount() elements.
  *
  * @param maxChildCount the maximum number of elements.
  */
 protected WeakReferenceList(final int maxChildCount)
 {
   this.maxChilds = maxChildCount;
   this.childs = new Reference[maxChildCount - 1];
 }
 /**
  * Returns the maximum number of children in this list.
  *
  * @return the maximum number of elements in this list.
  */
 protected final int getMaxChildCount()
 {
   return maxChilds;
 }
 /**
  * Returns the master element of this list. The master element is the element stored by a strong reference and cannot
  * be garbage collected.
  *
  * @return the master element
  */
 protected Object getMaster()
 {
   return master;
 }
 /**
  * Attempts to restore the child stored on the given index.
  *
  * @param index the index.
  * @return null if the child could not be restored or the restored child.
  */
 protected abstract Object restoreChild(int index);
 /**
  * Returns the child stored at the given index. If the child has been garbage collected, it gets restored using the
  * restoreChild function.
  *
  * @param index the index.
  * @return the object.
  */
 public Object get(final int index)
 {
   if (isMaster(index))
   {
     return master;
   }
   else
   {
     final Reference ref = childs[getChildPos(index)];
     if (ref == null)
     {
       throw new IllegalStateException("State: " + index);
     }
     Object ob = ref.get();
     if (ob == null)
     {
       ob = restoreChild(index);
       childs[getChildPos(index)] = createReference(ob);
     }
     return ob;
   }
 }
 /**
  * Replaces the child stored at the given index with the new child which can be null.
  *
  * @param report the object.
  * @param index  the index.
  */
 public void set(final Object report, final int index)
 {
   if (isMaster(index))
   {
     master = report;
   }
   else
   {
     childs[getChildPos(index)] = createReference(report);
   }
 }
 /**
  * Creates a new reference for the given object.
  *
  * @param o the object.
  * @return a WeakReference for the object o without any ReferenceQueue attached.
  */
 private Reference createReference(final Object o)
 {
   return new WeakReference(o);
 }
 /**
  * Adds the element to the list. If the maximum size of the list is exceeded, this function returns false to indicate
  * that adding failed.
  *
  * @param rs the object.
  * @return true, if the object was successfully added to the list, false otherwise
  */
 public boolean add(final Object rs)
 {
   if (size == 0)
   {
     master = rs;
     size = 1;
     return true;
   }
   else
   {
     if (size < getMaxChildCount())
     {
       childs[size - 1] = createReference(rs);
       size++;
       return true;
     }
     else
     {
       // was not able to add this to this list, maximum number of entries reached.
       return false;
     }
   }
 }
 /**
  * Returns true, if the given index denotes a master index of this list.
  *
  * @param index the index.
  * @return true if the index is a master index.
  */
 protected boolean isMaster(final int index)
 {
   return index % getMaxChildCount() == 0;
 }
 /**
  * Returns the internal storage position for the child.
  *
  * @param index the index.
  * @return the internal storage index.
  */
 protected int getChildPos(final int index)
 {
   return index % getMaxChildCount() - 1;
 }
 /**
  * Returns the size of the list.
  *
  * @return the size.
  */
 public int getSize()
 {
   return size;
 }
 /**
  * Serialisation support. The transient child elements were not saved.
  *
  * @param in the input stream.
  * @throws IOException            if there is an I/O error.
  * @throws ClassNotFoundException if a serialized class is not defined on this system.
  */
 private void readObject(final ObjectInputStream in)
     throws IOException, ClassNotFoundException
 {
   in.defaultReadObject();
   childs = new Reference[getMaxChildCount() - 1];
   for (int i = 0; i < childs.length; i++)
   {
     childs[i] = createReference(null);
   }
 }
 /**
  * Creates and returns a copy of this object.  The precise meaning of "copy" may depend on the class of the object.
* The general intent is that, for any object x, the expression:
*
   * x.clone() != x
* will be true, and that the expression:
*
   * x.clone().getClass() == x.getClass()
* will be true, but these are not absolute requirements. While it is typically the case that:
*
   * x.clone().equals(x)
  * will be true, this is not an absolute requirement.
  * <p/>
  * By convention, the returned object should be obtained by calling super.clone.  If a class and all of its
  * superclasses (except Object) obey this convention, it will be the case that x.clone().getClass() ==
  * x.getClass().
  * <p/>
  * By convention, the object returned by this method should be independent of this object (which is being cloned).  To
  * achieve this independence, it may be necessary to modify one or more fields of the object returned by
  * super.clone before returning it.  Typically, this means copying any mutable objects that comprise the
  * internal "deep structure" of the object being cloned and replacing the references to these objects with references
  * to the copies.  If a class contains only primitive fields or references to immutable objects, then it is usually
  * the case that no fields in the object returned by super.clone need to be modified.
  * <p/>
  * The method clone for class Object performs a specific cloning operation. First, if the class of
  * this object does not implement the interface Cloneable, then a CloneNotSupportedException is
  * thrown. Note that all arrays are considered to implement the interface Cloneable. Otherwise, this method
  * creates a new instance of the class of this object and initializes all its fields with exactly the contents of the
  * corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned.
  * Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.
  * <p/>
  * The class Object does not itself implement the interface Cloneable, so calling the clone
  * method on an object whose class is Object will result in throwing an exception at run time.
  *
  * @return a clone of this instance.
  * @throws CloneNotSupportedException if the object"s class does not support the Cloneable interface.
  *                                    Subclasses that override the clone method can also throw this
  *                                    exception to indicate that an instance cannot be cloned.
  * @see Cloneable
  */
 protected Object clone()
     throws CloneNotSupportedException
 {
   final WeakReferenceList list = (WeakReferenceList) super.clone();
   list.childs = (Reference[]) childs.clone();
   return list;
 }

}</source>