All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.jkcode.jkmvc.common.FixedKeyMapFactory Maven / Gradle / Ivy

package net.jkcode.jkmvc.common;

import net.jkcode.jkmvc.bit.IBitSet;
import org.apache.commons.collections.keyvalue.DefaultMapEntry;

import java.util.*;

/**
 * 有固定key的map的工厂
 *    主要是为2类场景准备
 *    1. 存储从jdbc结果集中读取的行数据
 *    2. OrmEntity 中的 data 属性的类型
 *
 * @author shijianhang<[email protected]>
 * @date 2019-03-12 8:22 PM
 */
public class FixedKeyMapFactory {

    /**
     * 固定的key
     */
    protected final String[] _keys;

    /**
     * 缓存key的哈希码, 加速key对比
     */
    protected final int[] _keyHashs;

    /**
     * 构造函数
     * @param keys
     */
    public FixedKeyMapFactory(final String... keys) {
        // 检查key是否有重复
        _keys = keys;
        List allKeys = Arrays.asList(keys);
        Set uniqueKeys = new HashSet(allKeys);
        if (uniqueKeys.size() != keys.length) {
            allKeys.removeAll(uniqueKeys);
            throw new IllegalArgumentException("The supplied keys must be unique, but the following keys are duplicated: " + allKeys);
        }

        // 计算key的哈希码
        _keyHashs = new int[keys.length];
        for (int i = 0; i < keys.length; i++)
            _keyHashs[i] = keys[i].hashCode();
    }

    /**
     * 创建有固定key的map
     * @param values
     * @return
     */
    public Map createMap(Object... values) {
        if (values.length == 0)
            values = new Object[_keys.length];

        if (values.length != _keys.length)
            throw new IllegalArgumentException("There are " + _keys.length + " keys, so that many values must be supplied");

        return new FixedKeyMap(values);
    }

    /**
     * 找到key的位置
     * @param key
     * @return -1表示未找到
     */
    public int indexOf(final Object key){
        int keyHashCode = key.hashCode();
        for (int i = 0; i < _keys.length; i++)
            if (_keyHashs[i] == keyHashCode && _keys[i].equals(key))
                return i;

        return -1;
    }

    /**
     * 有固定key的map
     */
    protected final class FixedKeyMap extends AbstractMap {

        /**
         * 值
         */
        protected final Object[] _values;

        /**
         * 被修改的key的标记, 就是标记被修改的key对应的index
         */
        protected final BitSet _dirtyBits = new BitSet(_keys.length);

        /**
         * entry集
         */
        protected transient Set> _entrySet;


        /**
         * 构造函数
         * @param values
         */
        protected FixedKeyMap(final Object[] values) {
            _values = values;
        }

        /**
         * 根据key获得value
         * @param key
         * @return
         */
        @Override
        public Object get(final Object key) {
            int i = indexOf(key);
            if(i == -1)
                return null;

            return _values[i];
        }

        /**
         * 检查是否没有元素
         * @return
         */
        @Override
        public boolean isEmpty() {
            return _dirtyBits.isEmpty();
        }

        /**
         * 检查是否包含key
         * @param key
         * @return
         */
        @Override
        public boolean containsKey(final Object key) {
            int i = indexOf(key);
            return i > -1 && _dirtyBits.get(i);
        }

        /**
         * 检查是否包含value
         * @param value
         * @return
         */
        @Override
        public boolean containsValue(final Object value) {
            // 遍历位
            for (int i = _dirtyBits.nextSetBit(0); i >= 0; i = _dirtyBits.nextSetBit(i+1)) {
                Object o = _values[i];
                if(value == null){
                    if(o == null)
                        return true;
                } else if(value.equals(o))
                    return true;
            }
            return false;
        }

        /**
         * 添加单个元素
         * @param key
         * @param value
         * @return
         */
        @Override
        public Object put(final String key, final Object value) {
            int i = indexOf(key);
            if(i == -1)
                throw new IllegalArgumentException("Unkown key: " + key);

            Object oldValue = _values[i];

            _values[i] = value;
            _dirtyBits.set(i);
            return oldValue;
        }

        /**
         * 删除key对应的元素
         * @param key
         * @return
         */
        @Override
        public Object remove(final Object key) {
            int i = indexOf(key);
            return remove(i);
        }

        /**
         * 删除位置对应的元素
         * @param i
         * @return
         */
        public Object remove(int i) {
            Object oldValue = _values[i];

            _values[i] = null;
            _dirtyBits.clear(i);
            return oldValue;
        }

        /**
         * 清除所有元素
         */
        @Override
        public void clear() {
            for(int i = 0; i < _values.length; i++)
                _values[i] = null;

            _dirtyBits.clear();
        }

        /*********************** EntrySet ************************/
        @Override
        public Set> entrySet() {
            if(_entrySet == null)
                _entrySet = new EntrySet();
            return _entrySet;
        }

        protected class EntrySet extends IBitSet> {

            public EntrySet() {
                super(_dirtyBits);
            }

            @Override
            public Entry getElement(int index) {
                try{
                    return new DefaultMapEntry(_keys[index], _values[index]);
                } catch (ArrayIndexOutOfBoundsException e) {
                    throw new NoSuchElementException();
                }
            }

            @Override
            public boolean removeElement(int index) {
                return FixedKeyMap.this.remove(index) != null;
            }

            public int size() {
                return _keys.length;
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy