⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractreferencemap.java

📁 iBATIS似乎已远离众说纷纭的OR框架之列
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
         * The reference is registered with the queue for later purging.
         *
         * @param type  HARD, SOFT or WEAK
         * @param referent  the object to refer to
         * @param hash  the hash code of the <i>key</i> of the mapping;
         *    this number might be different from referent.hashCode() if
         *    the referent represents a value and not a key
         */
        protected Object toReference(int type, Object referent, int hash) {
            switch (type) {
                case HARD: return referent;
                case SOFT: return new SoftRef(hash, referent, parent.queue);
                case WEAK: return new WeakRef(hash, referent, parent.queue);
                default: throw new Error();
            }
        }

        /**
         * Purges the specified reference
         * @param ref  the reference to purge
         * @return true or false
         */
        boolean purge(Reference ref) {
            boolean r = (parent.keyType > HARD) && (key == ref);
            r = r || ((parent.valueType > HARD) && (value == ref));
            if (r) {
                if (parent.keyType > HARD) {
                    ((Reference)key).clear();
                }
                if (parent.valueType > HARD) {
                    ((Reference)value).clear();
                } else if (parent.purgeValues) {
                    value = null;
                }
            }
            return r;
        }

        /**
         * Gets the next entry in the bucket.
         * 
         * @return the next entry in the bucket
         */
        protected ReferenceEntry next() {
            return (ReferenceEntry) next;
        }
    }

    //-----------------------------------------------------------------------
    /**
     * The EntrySet iterator.
     */
    static class ReferenceEntrySetIterator implements Iterator {
        /** The parent map */
        final AbstractReferenceMap parent;
        
        // These fields keep track of where we are in the table.
        int index;
        ReferenceEntry entry;
        ReferenceEntry previous;

        // These Object fields provide hard references to the
        // current and next entry; this assures that if hasNext()
        // returns true, next() will actually return a valid element.
        Object nextKey, nextValue;
        Object currentKey, currentValue;

        int expectedModCount;

        public ReferenceEntrySetIterator(AbstractReferenceMap parent) {
            super();
            this.parent = parent;
            index = (parent.size() != 0 ? parent.data.length : 0);
            // have to do this here!  size() invocation above
            // may have altered the modCount.
            expectedModCount = parent.modCount;
        }

        public boolean hasNext() {
            checkMod();
            while (nextNull()) {
                ReferenceEntry e = entry;
                int i = index;
                while ((e == null) && (i > 0)) {
                    i--;
                    e = (ReferenceEntry) parent.data[i];
                }
                entry = e;
                index = i;
                if (e == null) {
                    currentKey = null;
                    currentValue = null;
                    return false;
                }
                nextKey = e.getKey();
                nextValue = e.getValue();
                if (nextNull()) {
                    entry = entry.next();
                }
            }
            return true;
        }

        private void checkMod() {
            if (parent.modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
        }

        private boolean nextNull() {
            return (nextKey == null) || (nextValue == null);
        }

        protected ReferenceEntry nextEntry() {    
            checkMod();
            if (nextNull() && !hasNext()) {
                throw new NoSuchElementException();
            }
            previous = entry;
            entry = entry.next();
            currentKey = nextKey;
            currentValue = nextValue;
            nextKey = null;
            nextValue = null;
            return previous;
        }

        protected ReferenceEntry currentEntry() {
            checkMod();
            return previous;
        }
        
        public Object next() {
            return nextEntry();
        }

        public void remove() {
            checkMod();
            if (previous == null) {
                throw new IllegalStateException();
            }
            parent.remove(currentKey);
            previous = null;
            currentKey = null;
            currentValue = null;
            expectedModCount = parent.modCount;
        }
    }

    /**
     * The keySet iterator.
     */
    static class ReferenceKeySetIterator extends ReferenceEntrySetIterator {
        
        ReferenceKeySetIterator(AbstractReferenceMap parent) {
            super(parent);
        }
        
        public Object next() {
            return nextEntry().getKey();
        }
    }

    /**
     * The values iterator.
     */
    static class ReferenceValuesIterator extends ReferenceEntrySetIterator {
        
        ReferenceValuesIterator(AbstractReferenceMap parent) {
            super(parent);
        }
        
        public Object next() {
            return nextEntry().getValue();
        }
    }

    /**
     * The MapIterator implementation.
     */
    static class ReferenceMapIterator extends ReferenceEntrySetIterator implements MapIterator {
        
        protected ReferenceMapIterator(AbstractReferenceMap parent) {
            super(parent);
        }

        public Object next() {
            return nextEntry().getKey();
        }

        public Object getKey() {
            HashEntry current = currentEntry();
            if (current == null) {
                throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
            }
            return current.getKey();
        }

        public Object getValue() {
            HashEntry current = currentEntry();
            if (current == null) {
                throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
            }
            return current.getValue();
        }

        public Object setValue(Object value) {
            HashEntry current = currentEntry();
            if (current == null) {
                throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
            }
            return current.setValue(value);
        }
    }
    
    //-----------------------------------------------------------------------
    // These two classes store the hashCode of the key of
    // of the mapping, so that after they're dequeued a quick
    // lookup of the bucket in the table can occur.

    /**
     * A soft reference holder.
     */
    static class SoftRef extends SoftReference {
        /** the hashCode of the key (even if the reference points to a value) */
        private int hash;

        public SoftRef(int hash, Object r, ReferenceQueue q) {
            super(r, q);
            this.hash = hash;
        }

        public int hashCode() {
            return hash;
        }
    }

    /**
     * A weak reference holder.
     */
    static class WeakRef extends WeakReference {
        /** the hashCode of the key (even if the reference points to a value) */
        private int hash;

        public WeakRef(int hash, Object r, ReferenceQueue q) {
            super(r, q);
            this.hash = hash;
        }

        public int hashCode() {
            return hash;
        }
    }

    //-----------------------------------------------------------------------
    /**
     * Replaces the superclass method to store the state of this class.
     * <p>
     * Serialization is not one of the JDK's nicest topics. Normal serialization will
     * initialise the superclass before the subclass. Sometimes however, this isn't
     * what you want, as in this case the <code>put()</code> method on read can be
     * affected by subclass state.
     * <p>
     * The solution adopted here is to serialize the state data of this class in
     * this protected method. This method must be called by the
     * <code>writeObject()</code> of the first serializable subclass.
     * <p>
     * Subclasses may override if they have a specific field that must be present
     * on read before this implementation will work. Generally, the read determines
     * what must be serialized here, if anything.
     * 
     * @param out  the output stream
     */
    protected void doWriteObject(ObjectOutputStream out) throws IOException {
        out.writeInt(keyType);
        out.writeInt(valueType);
        out.writeBoolean(purgeValues);
        out.writeFloat(loadFactor);
        out.writeInt(data.length);
        for (MapIterator it = mapIterator(); it.hasNext();) {
            out.writeObject(it.next());
            out.writeObject(it.getValue());
        }
        out.writeObject(null);  // null terminate map
        // do not call super.doWriteObject() as code there doesn't work for reference map
    }

    /**
     * Replaces the superclassm method to read the state of this class.
     * <p>
     * Serialization is not one of the JDK's nicest topics. Normal serialization will
     * initialise the superclass before the subclass. Sometimes however, this isn't
     * what you want, as in this case the <code>put()</code> method on read can be
     * affected by subclass state.
     * <p>
     * The solution adopted here is to deserialize the state data of this class in
     * this protected method. This method must be called by the
     * <code>readObject()</code> of the first serializable subclass.
     * <p>
     * Subclasses may override if the subclass has a specific field that must be present
     * before <code>put()</code> or <code>calculateThreshold()</code> will work correctly.
     * 
     * @param in  the input stream
     */
    protected void doReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        this.keyType = in.readInt();
        this.valueType = in.readInt();
        this.purgeValues = in.readBoolean();
        this.loadFactor = in.readFloat();
        int capacity = in.readInt();
        init();
        data = new HashEntry[capacity];
        while (true) {
            Object key = in.readObject();
            if (key == null) {
                break;
            }
            Object value = in.readObject();
            put(key, value);
        }
        threshold = calculateThreshold(data.length, loadFactor);
        // do not call super.doReadObject() as code there doesn't work for reference map
    }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -