Package com.github.jsonj

Source Code of com.github.jsonj.SimpleIntKeyMap$EntryImpl

package com.github.jsonj;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;

import org.apache.commons.lang.Validate;

/**
* Performant array list based map for small number of entries. Get performs linearly for number of entries however, it
* uses vastly less memory and it is actually fast enough for small numbers of entries.
*/
public class SimpleIntKeyMap<V> implements Map<Integer, V>, Serializable {

    private static final long serialVersionUID = 7650009698202273725L;
    private boolean immutable=false;

    int[] keysArr=new int[3];
    private final ArrayList<V> values = new ArrayList<>();

    public void makeImmutable() {
        immutable=true;
    }

    @Override
    public int size() {
        return values.size();
    }

    @Override
    public boolean isEmpty() {
        return values.size() == 0;
    }

    @Override
    public boolean containsKey(Object key) {
        return containsIntKey((Integer)key);
    }

    public boolean containsIntKey(int key) {
        for(int i=0; i<values.size();i++) {
            int k = keysArr[i];
            if(key == k) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean containsValue(Object value) {
        for(V e: values) {
            if(e.equals(value)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public V get(Object key) {
        return getWithIntKey((Integer)key);
    }

    public V getWithIntKey(int key) {
        int index = getIndex(key);
        if(index>=0) {
            return values.get(index);
        } else {
            return null;
        }
    }

    private int getIndex(int key) {
        int j=0;
        for(int i=0; i<values.size();i++) {
            int k = keysArr[i];
            if(key == k) {
                return j;
            }
            j++;
        }
        return -1;
    }

    @Override
    public V put(Integer key, V value) {
        if(immutable) {
            throw new IllegalStateException("object is immutable");
        }
        Validate.notNull(key);
        int index = getIndex(key);
        if(index >=0) {
            values.set(index, value);
        } else {
            if(values.size()+1<keysArr.length) {
                // dynamically grow array
                keysArr = Arrays.copyOf(keysArr, keysArr.length + 3);
            }
            keysArr[values.size()] = key;
            values.add(value);
        }
        return value;
    }

    @Override
    public V remove(Object key) {
        if(immutable) {
            throw new IllegalStateException("object is immutable");
        }

        int index = getIndex((Integer)key);
        if(index >=0) {
            System.arraycopy(keysArr,index+1,keysArr,index,keysArr.length-1-index);
            return values.remove(index);
        } else {
            return null;
        }
    }

    @Override
    public void putAll(java.util.Map<? extends Integer, ? extends V> m) {
        if(immutable) {
            throw new IllegalStateException("object is immutable");
        }

        for (Entry<? extends Integer, ? extends V> e : m.entrySet()) {
            put(e.getKey(), e.getValue());
        }
    };

    @Override
    public void clear() {
        keysArr = new int[5];
        values.clear();
    }

    @Override
    public Set<Integer> keySet() {
        Set<Integer> result = new HashSet<>();
        for(int i=0; i<values.size();i++) {
            result.add(keysArr[i]);
        }
        return result;
    }

    @Override
    public Collection<V> values() {
        return Collections.unmodifiableList(values);
    }

    @Override
    public Set<Entry<Integer, V>> entrySet() {

        return new EntrySet(this);
    }

    private class EntrySet implements Set<Entry<Integer, V>> {

        private final SimpleIntKeyMap<V> owner;

        public EntrySet(SimpleIntKeyMap<V> simpleMap) {
            this.owner = simpleMap;
        }

        @Override
        public int size() {
            return owner.size();
        }

        @Override
        public boolean isEmpty() {
            return owner.isEmpty();
        }

        @Override
        public boolean contains(Object o) {
            @SuppressWarnings("unchecked")
            Entry<Integer, JsonElement> e = (Entry<Integer, JsonElement>) o;
            int index = owner.getIndex(e.getKey());
            if(index >=0) {
                return values.get(index).equals(e.getValue());
            } else {
                return false;
            }
        }

        @Override
        public Iterator<Entry<Integer, V>> iterator() {
            return new Iterator<Map.Entry<Integer,V>>() {
                int startSize=size();
                int index=0;

                @Override
                public boolean hasNext() {
                    if(size() != startSize) {
                        throw new ConcurrentModificationException();
                    }
                    return index < values.size();
                }

                @Override
                public Entry<Integer, V> next() {
                    if(hasNext()) {
                        EntryImpl next = new EntryImpl(keysArr[index], values.get(index));
                        index++;
                        return next;
                    } else {
                        throw new NoSuchElementException();
                    }
                }

                @Override
                public void remove() {
                    if(immutable) {
                        throw new IllegalStateException("object is immutable");
                    }

                    if(owner.size() == 0) {
                        throw new NoSuchElementException("The entry set is empty");
                    }
                    if(index == 0) {
                        throw new IllegalStateException("next has not been called yet");
                    }
                    int removeIndex = index-1;
                    System.arraycopy(keysArr,removeIndex+1,keysArr,removeIndex,keysArr.length-1-removeIndex);
                    values.remove(removeIndex);
                    index--;
                    startSize--;
                }
            };
        }

        @Override
        public Object[] toArray() {
            @SuppressWarnings("unchecked")
            Entry<Integer,V>[] result = new Entry[owner.size()];
            int i=0;
            for(Entry<Integer,V> e: this) {
                result[i] = e;
                i++;
            }
            return result;
        }

        @SuppressWarnings("unchecked")
        @Override
        public <T> T[] toArray(T[] a) {
            return (T[]) toArray();
        }

        @Override
        public boolean add(Entry<Integer, V> e) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean remove(Object o) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean containsAll(Collection<?> c) {
            for(Object o: c) {
                if(!contains(o)) {
                    return false;
                }
            }
            return true;
        }

        @Override
        public boolean addAll(Collection<? extends java.util.Map.Entry<Integer, V>> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean retainAll(Collection<?> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean removeAll(Collection<?> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void clear() {
            throw new UnsupportedOperationException();
        }
    }

    private class EntryImpl implements Entry<Integer, V> {
        private final int key;
        private final V value;

        public EntryImpl(int key, V value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public Integer getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public V setValue(V value) {
            throw new UnsupportedOperationException("Entries are immutable");
        }

        @Override
        public boolean equals(Object obj) {
            return Objects.deepEquals(this, obj);
        }

        @Override
        public int hashCode() {
            return Objects.hash(key,value);
        }

        @Override
        public String toString() {
            return key +":"+value;
        }
    }
}
TOP

Related Classes of com.github.jsonj.SimpleIntKeyMap$EntryImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.