001         package com.croftsoft.core.util;
002    
003         import java.lang.ref.*;
004         import java.util.*;
005    
006         /*********************************************************************
007         * A Map implementation that dumps its content when memory runs low.
008         *
009         * <P>
010         *
011         * Backed by a WeakHashMap.  Note that an entry will not be garbage
012         * collected if its key remains strongly reachable.
013         *
014         * <P>
015         *
016         * @see
017         *   java.util.WeakHashMap
018         * @see
019         *   java.lang.ref.SoftReference
020         *
021         * @version
022         *   1999-04-20
023         * @author
024         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
025         *********************************************************************/
026    
027         public class  SoftHashMap extends AbstractMap
028         //////////////////////////////////////////////////////////////////////
029         //////////////////////////////////////////////////////////////////////
030         {
031    
032         private WeakHashMap     weakHashMap    = new WeakHashMap    ( );
033         private ReferenceQueue  referenceQueue = new ReferenceQueue ( );
034         private Set             softSet        = new HashSet        ( );
035    
036         //////////////////////////////////////////////////////////////////////
037         //////////////////////////////////////////////////////////////////////
038    
039         public static void  main ( String [ ]  args )
040         //////////////////////////////////////////////////////////////////////
041         {
042           System.out.println ( test ( ) );
043         }
044    
045         public static boolean  test ( )
046         //////////////////////////////////////////////////////////////////////
047         {
048           try
049           {
050             SoftHashMap  softHashMap = new SoftHashMap ( );
051    
052             softHashMap.put ( "key", "value" );
053    
054             if ( !softHashMap.remove ( "key" ).equals ( "value" )
055               || ( softHashMap.size ( ) > 0 ) )
056             {
057               return false;
058             }
059    
060             Runtime  runtime = Runtime.getRuntime ( );
061    
062             for ( int  i = 0; i < 1000000; i++ )
063             {
064               if ( i % 10000 == 0 )
065               {
066                 System.out.println (
067                   i + ":  "
068                   + softHashMap.size ( )
069                   + " entries, "
070                   + runtime.freeMemory ( )
071                   + " / "
072                   + runtime.totalMemory ( )
073                   + " memory usage" );
074               }
075    
076               Integer  value = new Integer ( i );
077               softHashMap.put ( value.toString ( ), value );
078             }
079           }
080           catch ( Throwable  t )
081           {
082             t.printStackTrace ( );
083    
084             return false;
085           }
086    
087           return true;
088         }
089    
090         //////////////////////////////////////////////////////////////////////
091         //////////////////////////////////////////////////////////////////////
092    
093         public Set  entrySet ( )
094         //////////////////////////////////////////////////////////////////////
095         {
096           clearQueue ( );
097    
098           return weakHashMap.entrySet ( );
099         }
100    
101         public Object  put ( Object  key, Object  value )
102         //////////////////////////////////////////////////////////////////////
103         {
104           clearQueue ( );
105    
106           softSet.add ( new SoftReference ( key, referenceQueue ) );
107    
108           return weakHashMap.put ( key, value );
109         }
110    
111         //////////////////////////////////////////////////////////////////////
112         //////////////////////////////////////////////////////////////////////
113    
114         public void  clearQueue ( )
115         //////////////////////////////////////////////////////////////////////
116         {
117           Reference  reference = null;
118           while ( ( reference = referenceQueue.poll ( ) ) != null )
119           {
120             softSet.remove ( reference );
121           }
122         }
123    
124         //////////////////////////////////////////////////////////////////////
125         //////////////////////////////////////////////////////////////////////
126         }