alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.editor.ext;

import org.netbeans.editor.StringMap;

/**
* Cache holding the most commonly used strings.
* The unused strings are discarded when they reach the end of chain.
*
* @author Miloslav Metelka
* @version 1.00
*/

public class StringCache {

    private static final int DEFAULT_MAX_SIZE = 300;

    private static final int DEFAULT_INITIAL_CAPACITY = 701;

    int maxSize;

    int size;

    StringMap strMap;

    /** First chain member */
    private Entry chain;

    /** Last chain member */
    private Entry endChain;

    /** Last entry that was made free */
    private Entry freeEntry;

    public int statQueries; // count of queries
    public int statHits; // count of cache hits

    public StringCache() {
        this(DEFAULT_MAX_SIZE, DEFAULT_INITIAL_CAPACITY);
    }

    public StringCache(int maxSize) {
        this(maxSize, 2 * maxSize);
    }

    public StringCache(int maxSize, int initialMapCapacity) {
        this.maxSize = maxSize;
        strMap = new StringMap(initialMapCapacity);
    }

    private void toStart(Entry e) {
        if (e != chain) {
            // chain removal
            Entry ep = e.prev; // ep surely not null
            Entry en = e.next;
            if (en != null) {
                en.prev = ep;
            } else { // last chain member
                endChain = ep;
            }
            ep.next = en;

            // insert to chain start
            if (chain != null) {
                e.next = chain;
                chain.prev = e;
            }
            chain = e;
        }
    }

    public String getString(char[] chars, int offset, int len) {
        statQueries++;
        Object o = strMap.get(chars, offset, len);
        String ret;
        if (o instanceof Entry) {
            Entry e = (Entry)o;
            toStart(e);
            statHits++;
            ret = e.str;
        } else if (o instanceof String) {
            statHits++;
            ret = (String)o;
        } else { // string not found in cache
            ret = new String(chars, offset, len);
            storeString(ret);
        }
        return ret;
    }

    /** Remove string that can be in the cache */
    private void removeString(String s) {
        Object o = strMap.remove(s);
        if (o instanceof Entry) {
            Entry e = (Entry)o;
            Entry ep = e.prev;
            Entry en = e.next;

            if (e == chain) {
                chain = en;
                if (e == endChain) {
                    endChain = null;
                }
            } else { // not begining of chain
                if (en != null) {
                    en.prev = ep;
                } else {
                    endChain = ep;
                }
            }

            freeEntry = e; // free - can be reused for addition
            size--;
        }
        /* In other cases the removed object was either
        * the string which should be fine here
        * or it was null.
        */
    }

    /** Store string that's not yet in the cache */
    private void storeString(String s) {
        Entry e;
        if (size >= maxSize) {
            // take last one and move to begining and replace value
            e = endChain;
            toStart(e);
            strMap.remove(e.str);
            e.str = s;
        } else { // count of entries less than max
            if (freeEntry != null) {
                e = freeEntry;
                freeEntry = null;
                e.str = s;
                e.next = chain;
            } else {
                e = new Entry(s, chain);
            }

            if (chain != null) {
                chain.prev = e;
            } else { // nothing inserted yet
                endChain = e;
            }
            chain = e;
            size++;
        }
        strMap.put(s, e);
    }

    /** Put a string into cache that will survive there
    * so that it will be never removed.
    */
    public void putSurviveString(String s) {
        removeString(s);
        strMap.put(s, s);
    }

    static class Entry {

        Entry(String str, Entry next) { // prev always null
            this.str = str;
            this.next = next;
        }

        String str;

        Entry next;

        Entry prev;

    }

    public String toString() {
        String ret = "size=" + size + ", maxSize=" + maxSize // NOI18N
                     + ", statHits=" + statHits + ", statQueries=" + statQueries; // NOI18N
        if (statQueries > 0) {
            ret += ", hit ratio=" + (statHits * 100 / statQueries) + "%"; // NOI18N
        }
        return ret;
    }

}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.