SoftHashMap.java Source code

Java tutorial

Introduction

Here is the source code for SoftHashMap.java

Source

import java.util.*;
import java.lang.ref.*;

public class SoftHashMap extends AbstractMap implements Map {

    private Set entrySet = null;
    private Map hash;
    private ReferenceQueue queue = new ReferenceQueue();

    static private class SoftKey extends SoftReference {
        private int hash;

        private SoftKey(Object k) {
            super(k);
            hash = k.hashCode();
        }

        private static SoftKey create(Object k) {
            if (k == null) {
                return null;
            } else {
                return new SoftKey(k);
            }
        }

        private SoftKey(Object k, ReferenceQueue q) {
            super(k, q);
            hash = k.hashCode();
        }

        private static SoftKey create(Object k, ReferenceQueue q) {
            if (k == null) {
                return null;
            } else {
                return new SoftKey(k, q);
            }
        }

        public boolean equals(Object o) {
            if (this == o) {
                return true;
            } else if (!(o instanceof SoftKey)) {
                return false;
            }
            Object t = this.get();
            Object u = ((SoftKey) o).get();
            if ((t == null) || (u == null)) {
                return false;
            } else if (t == u) {
                return true;
            } else {
                return t.equals(u);
            }
        }

        public int hashCode() {
            return hash;
        }
    }

    private void processQueue() {
        SoftKey sk;
        while ((sk = (SoftKey) queue.poll()) != null) {
            hash.remove(sk);
        }
    }

    public SoftHashMap() {
        hash = new HashMap();
    }

    public SoftHashMap(Map t) {
        this(Math.max(2 * t.size(), 11), 0.75f);
        putAll(t);
    }

    public SoftHashMap(int initialCapacity) {
        hash = new HashMap(initialCapacity);
    }

    public SoftHashMap(int initialCapacity, float loadFactor) {
        hash = new HashMap(initialCapacity, loadFactor);
    }

    public int size() {
        return entrySet().size();
    }

    public boolean isEmpty() {
        return entrySet().isEmpty();
    }

    public boolean containsKey(Object key) {
        return hash.containsKey(SoftKey.create(key));
    }

    public Object get(Object key) {
        return hash.get(SoftKey.create(key));
    }

    public Object put(Object key, Object value) {
        processQueue();
        return hash.put(SoftKey.create(key, queue), value);
    }

    public Object remove(Object key) {
        processQueue();
        return hash.remove(SoftKey.create(key));
    }

    public void clear() {
        processQueue();
        hash.clear();
    }

    private static class Entry implements Map.Entry {
        private Map.Entry ent;
        private Object key;

        Entry(Map.Entry ent, Object key) {
            this.ent = ent;
            this.key = key;
        }

        public Object getKey() {
            return key;
        }

        public Object getValue() {
            return ent.getValue();
        }

        public Object setValue(Object value) {
            return ent.setValue(value);
        }

        public boolean equals(Object o) {
            if (!(o instanceof Map.Entry)) {
                return false;
            } else {
                Map.Entry e = (Map.Entry) o;
                Object value = getValue();
                return (key == null ? e.getKey() == null : key.equals(e.getKey()))
                        && (value == null ? e.getValue() == null : value.equals(e.getValue()));
            }
        }

        public int hashCode() {
            Object value = getValue();
            return (((key == null) ? 0 : key.hashCode()) ^ ((value == null) ? 0 : value.hashCode()));
        }

    }

    public Set entrySet() {
        if (entrySet == null) {
            entrySet = new EntrySet();
        }
        return entrySet;
    }

    private class EntrySet extends AbstractSet {
        Set set = hash.entrySet();

        public Iterator iterator() {

            return new Iterator() {
                Iterator iter = set.iterator();
                Entry next = null;

                public boolean hasNext() {
                    while (iter.hasNext()) {
                        Map.Entry ent = (Map.Entry) iter.next();
                        SoftKey sk = (SoftKey) ent.getKey();
                        Object k = null;
                        if ((sk != null) && ((k = sk.get()) == null)) {
                            /* Soft key has been cleared by GC */
                            continue;
                        }
                        next = new Entry(ent, k);
                        return true;
                    }
                    return false;
                }

                public Object next() {
                    if ((next == null) && !hasNext()) {
                        throw new NoSuchElementException();
                    }
                    Entry element = next;
                    next = null;
                    return element;
                }

                public void remove() {
                    iter.remove();
                }
            };
        }

        public boolean isEmpty() {
            return !(iterator().hasNext());
        }

        public int size() {
            int size = 0;
            for (Iterator i = iterator(); i.hasNext(); i.next(), size++)
                ;
            return size;
        }

        public boolean remove(Object o) {
            processQueue();
            if (!(o instanceof Map.Entry)) {
                return false;
            }
            Map.Entry e = (Map.Entry) o;
            Object ev = e.getValue();
            SoftKey sk = SoftKey.create(e.getKey());
            Object hv = hash.get(sk);
            if ((hv == null) ? ((ev == null) && hash.containsKey(sk)) : hv.equals(ev)) {
                hash.remove(sk);
                return true;
            }
            return false;
        }

        public int hashCode() {
            int h = 0;
            for (Iterator i = set.iterator(); i.hasNext();) {
                Map.Entry ent = (Map.Entry) i.next();
                SoftKey sk = (SoftKey) ent.getKey();
                Object v;
                if (sk == null) {
                    continue;
                }
                h += (sk.hashCode() ^ (((v = ent.getValue()) == null) ? 0 : v.hashCode()));
            }
            return h;
        }
    }
}