org.culturegraph.mf.util.tries.CharMap.java Source code

Java tutorial

Introduction

Here is the source code for org.culturegraph.mf.util.tries.CharMap.java

Source

/*
 *  Copyright 2013, 2014 Deutsche Nationalbibliothek
 *
 *  Licensed under the Apache License, Version 2.0 the "License";
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.culturegraph.mf.util.tries;

import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.NotImplementedException;

/**
 * A {@link Map} with char as key. Used for set matching, tries etc. <br>
 * <strong>Important:</strong> It is optimized for size in memory. No extra information for fast entry/keySet/values iteration etc. is held.
 * 
 * @author Markus Michael Geipel
 * 
 * @param <V>
 */
final class CharMap<V> implements Map<Character, V> {

    private static final int INITIAL_CAPACITY = 2;
    private static final float LOAD_FACTOR = 1f;
    private Entry<V>[] table;

    private int size;

    @SuppressWarnings("unchecked")
    public CharMap() {
        table = new Entry[INITIAL_CAPACITY];
    }

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

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

    @Override
    public boolean containsKey(final Object key) {
        throw new NotImplementedException();
    }

    @Override
    public boolean containsValue(final Object value) {
        throw new NotImplementedException();
    }

    @Override
    public V get(final Object key) {
        if (key instanceof Character) {
            final Character beite = (Character) key;
            return get(beite.charValue());
        }
        return null;
    }

    public V get(final char key) {

        Entry<V> entry = table[key % table.length];
        while (entry != null) {
            if (entry.getKeyChar() == key) {
                return entry.getValue();
            }
            entry = entry.getNext();
        }
        return null;
    }

    @Override
    public V put(final Character key, final V value) {
        put(key.charValue(), value);
        return null;
    }

    /**
     * @param key
     * @param value
     * @return the parameter value
     */
    public void put(final char key, final V value) {
        if (size > LOAD_FACTOR * table.length) {
            expand();
        }
        put(table, key, value);
        ++size;
    }

    public void put(final Entry<V>[] table, final char key, final V value) {
        final Entry<V> newEntry = new Entry<V>(key, value);

        Entry<V> entry = table[key % table.length];

        if (entry == null) {
            table[key % table.length] = newEntry;
        } else {
            while (entry.getNext() != null) {
                if (entry.getKeyChar() == key) {
                    throw new IllegalStateException("Key '" + key + "' already used");
                }
                entry = entry.getNext();
            }
            entry.setNext(newEntry);
        }
    }

    private void expand() {
        final int newSize = 2 * table.length;
        @SuppressWarnings("unchecked")
        final Entry<V>[] newTable = new Entry[newSize];

        for (Entry<V> entry : table) {
            Entry<V> temp = entry;
            while (temp != null) {
                put(newTable, temp.getKeyChar(), temp.getValue());
                temp = temp.getNext();
            }
        }

        table = newTable;
    }

    @Override
    public V remove(final Object key) {
        throw new NotImplementedException();
    }

    @Override
    public void putAll(final Map<? extends Character, ? extends V> map) {
        throw new NotImplementedException();
    }

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

    @Override
    public Set<Character> keySet() {
        final Set<Character> keys = new HashSet<Character>();
        for (int i = 0; i < table.length; ++i) {
            Entry<V> entry = table[i];
            while (entry != null) {
                keys.add(entry.getKey());
                entry = entry.getNext();
            }
        }
        return keys;
    }

    @Override
    public Collection<V> values() {
        final Set<V> values = new HashSet<V>();
        for (int i = 0; i < table.length; ++i) {
            Entry<V> entry = table[i];
            while (entry != null) {
                values.add(entry.getValue());
                entry = entry.getNext();
            }
        }
        return values;
    }

    @Override
    public Set<java.util.Map.Entry<Character, V>> entrySet() {
        final Set<java.util.Map.Entry<Character, V>> entries = new HashSet<java.util.Map.Entry<Character, V>>();
        for (int i = 0; i < table.length; ++i) {
            Entry<V> entry = table[i];
            while (entry != null) {
                entries.add(entry);
                entry = entry.getNext();
            }
        }
        return entries;
    }

    /**
     * 
     * @param <V>
     */
    private static final class Entry<V> implements Map.Entry<Character, V> {
        private final char key;
        private V value;
        private Entry<V> next;

        Entry(final char key, final V value) {
            this.key = key;
            this.value = value;
        }

        public Entry<V> getNext() {
            return next;
        }

        public char getKeyChar() {
            return key;
        }

        public void setNext(final Entry<V> next) {
            this.next = next;
        }

        @Override
        public Character getKey() {
            return Character.valueOf(key);
        }

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

        @Override
        public V setValue(final V value) {
            final V old = this.value;
            this.value = value;
            return old;
        }

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