OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Blame | Last modification | View Log | RSS feed

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
 * 
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each file.
 */
 
 package org.openconcerto.utils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Map optimisée pour les petites tailles (<50).
 * 
 * Empreinte mémoire divisée 4 par rapport à HashMap.
 * 
 * N'implemente pas Map pour ne pas exposer des méthodes sous-optimales
 * 
 */
public class QuickOrderedMap<K, V> {

    private final ArrayList<Object> keysAndValues;

    public QuickOrderedMap() {
        this(10);
    }

    public QuickOrderedMap(int initialCapacity) {
        this.keysAndValues = new ArrayList<>(initialCapacity * 2);
    }

    public int size() {
        return this.keysAndValues.size() / 2;
    }

    public boolean isEmpty() {
        return this.keysAndValues.isEmpty();
    }

    public boolean containsKey(K key) {
        final int size = this.keysAndValues.size();
        for (int i = 0; i < size; i += 2) {
            if (this.keysAndValues.get(i).equals(key)) {
                return true;
            }
        }
        return false;
    }

    public boolean containsValue(V value) {
        final int size = this.keysAndValues.size();
        for (int i = 1; i < size; i += 2) {
            if (this.keysAndValues.get(i).equals(value)) {
                return true;
            }
        }
        return false;
    }

    @SuppressWarnings("unchecked")
    public K getKey(int index) {
        return (K) this.keysAndValues.get(index * 2);
    }

    @SuppressWarnings("unchecked")
    public V getValue(int index) {
        return (V) this.keysAndValues.get(1 + index * 2);
    }

    @SuppressWarnings("unchecked")
    public V get(K key) {
        final int size = this.keysAndValues.size();
        for (int i = 0; i < size; i += 2) {
            if (this.keysAndValues.get(i).equals(key)) {

                return (V) this.keysAndValues.get(i + 1);
            }
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public V put(K key, V value) {
        final int size = this.keysAndValues.size();
        for (int i = 0; i < size; i += 2) {
            if (this.keysAndValues.get(i).equals(key)) {
                final Object old = this.keysAndValues.get(i + 1);
                this.keysAndValues.set(i + 1, value);
                return (V) old;
            }
        }
        this.keysAndValues.add(key);
        this.keysAndValues.add(value);
        return null;
    }

    @SuppressWarnings("unchecked")
    public V remove(K key) {
        final int size = this.keysAndValues.size();
        for (int i = 0; i < size; i += 2) {
            if (this.keysAndValues.get(i).equals(key)) {
                this.keysAndValues.remove(i);
                return (V) this.keysAndValues.remove(i);
            }
        }
        return null;
    }

    public void putAll(Map<? extends K, ? extends V> m) {
        final Set<? extends K> keySet = m.keySet();
        if (!isEmpty()) {
            for (Iterator<? extends K> iterator = keySet.iterator(); iterator.hasNext();) {
                K key = iterator.next();
                put(key, m.get(key));
            }
        } else {
            for (Iterator<? extends K> iterator = keySet.iterator(); iterator.hasNext();) {
                K key = iterator.next();
                this.keysAndValues.add(key);
                this.keysAndValues.add(m.get(key));
            }
        }
    }

    public void clear() {
        this.keysAndValues.clear();
    }

}