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

org.javersion.util.AbstractHashMap Maven / Gradle / Ivy

There is a newer version: 0.15.3
Show newest version
/*
 * Copyright 2013 Samppa Saarela
 *
 * 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.javersion.util;

import static com.google.common.collect.Iterators.transform;

import java.util.Iterator;
import java.util.Map;
import java.util.Objects;

import org.javersion.util.AbstractHashMap.EntryNode;

import com.google.common.base.Function;
import com.google.common.collect.Iterables;

public abstract class AbstractHashMap>
        extends AbstractHashTrie, AbstractHashMap>
        implements Iterable> {

    @SuppressWarnings("rawtypes")
    private static final Function TO_ENTRY = (Object input) -> toEntry((Map.Entry) input);

    public This assoc(K key, V value) {
        return assoc(new EntryNode(key, value));
    }

    private This assoc(java.util.Map.Entry entry) {
        return merge(entry, null);
    }

    public This assocAll(Map map) {
        return mergeAll(map, null);
    }

    public This assocAll(Iterable> entries) {
        return mergeAll(entries, null);
    }


    public This merge(K key, V value, Merger> merger) {
        return doMerge(new EntryNode(key, value), merger);
    }

    public This merge(Map.Entry entry, Merger> merger) {
        return doMerge(toEntry(entry), merger);
    }

    @SuppressWarnings("unchecked")
    protected This doMerge(EntryNode entry, Merger> merger) {
        final UpdateContext> updateContext = updateContext(1, merger);
        return (This) doAdd(updateContext, entry);
    }


    @SuppressWarnings("unchecked")
    public This mergeAll(Map map, Merger> merger) {
        final UpdateContext> updateContext = updateContext(map.size(), merger);
        return (This) doAddAll(updateContext, transform(map.entrySet().iterator(), TO_ENTRY));
    }

    @SuppressWarnings("unchecked")
    public This mergeAll(Iterable> entries, Merger> merger) {
        final UpdateContext> updateContext = updateContext(32, merger);
        return (This) doAddAll(updateContext, transform(entries.iterator(), TO_ENTRY));
    }

    protected UpdateContext> updateContext(int expectedSize, Merger> merger) {
        return new UpdateContext<>(expectedSize, merger);
    }


    public This dissoc(Object key) {
        return dissoc(key, null);
    }

    @SuppressWarnings("unchecked")
    public This dissoc(Object key, Merger> merger) {
        final UpdateContext> updateContext = updateContext(1, merger);
        return (This) doRemove(updateContext, key);
    }

    public V get(Object key) {
        EntryNode entry = root().find(key);
        return entry != null ? entry.getValue() : null;
    }

    public boolean containsKey(Object key) {
        return root().find(key) != null;
    }

    public Iterator> iterator() {
        return transform(doIterator(), Map.Entry.class::cast);
    }

    public Iterable keys() {
        return Iterables.transform(this, MapUtils.mapKeyFunction());
    }

    public Iterable values() {
        return Iterables.transform(this, MapUtils.mapValueFunction());
    }


    @SuppressWarnings("unchecked")
    protected static  EntryNode toEntry(Map.Entry entry) {
        if (entry instanceof EntryNode) {
            return (EntryNode) entry;
        } else {
            return new EntryNode<>(entry.getKey(), entry.getValue());
        }
    }

    public static final class EntryNode extends AbstractHashTrie.EntryNode> implements Map.Entry {

        final V value;

        public EntryNode(K key, V value) {
            super(key);
            this.value = value;
        }
        @Override
        public K getKey() {
            return key;
        }

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

        @Override
        public V setValue(V value) {
            throw new UnsupportedOperationException();
        }

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

        @Override
        public Node> assocInternal(final UpdateContext>  currentContext, final int shift, final int hash, final EntryNode newEntry) {
            if (Objects.equals(key, newEntry.key)) {
                if (Objects.equals(value, newEntry.value)) {
                    return this;
                }
                return currentContext.merge(this, newEntry) ? newEntry : this;
            }
            return split(currentContext, shift, hash, newEntry);
        }
    }

    static class EntrySpliterator extends NodeSpliterator, K, EntryNode> {

        public EntrySpliterator(Node> node, int sizeEstimate, boolean immutable) {
            super(node, sizeEstimate, DISTINCT | (immutable ? IMMUTABLE : 0));
        }

        private EntrySpliterator(Node>[] array, int pos, int limit, int sizeEstimate, boolean immutable) {
            super(array, pos, limit, sizeEstimate, DISTINCT | (immutable ? IMMUTABLE : 0));
        }

        @Override
        protected NodeSpliterator, K, EntryNode> newSubSpliterator(Node>[] array, int pos, int limit, int sizeEstimate) {
            return new EntrySpliterator<>(array, pos, limit, sizeEstimate, hasCharacteristics(IMMUTABLE));
        }

        @Override
        protected Map.Entry apply(EntryNode entry) {
            return entry;
        }

    }

    static class KeySpliterator extends NodeSpliterator> {

        public KeySpliterator(Node> node, int sizeEstimate, boolean immutable) {
            super(node, sizeEstimate, DISTINCT | (immutable ? IMMUTABLE : 0));
        }

        private KeySpliterator(Node>[] array, int pos, int limit, int sizeEstimate, boolean immutable) {
            super(array, pos, limit, sizeEstimate, DISTINCT | (immutable ? IMMUTABLE : 0));
        }

        @Override
        protected NodeSpliterator> newSubSpliterator(Node>[] array, int pos, int limit, int sizeEstimate) {
            return new KeySpliterator<>(array, pos, limit, sizeEstimate, hasCharacteristics(IMMUTABLE));
        }

        @Override
        protected K apply(EntryNode entry) {
            return entry.getKey();
        }

    }

    static class ValueSpliterator extends NodeSpliterator> {

        public ValueSpliterator(Node> node, int sizeEstimate, boolean immutable) {
            super(node, sizeEstimate, (immutable ? IMMUTABLE : 0));
        }

        private ValueSpliterator(Node>[] array, int pos, int limit, int sizeEstimate, boolean immutable) {
            super(array, pos, limit, sizeEstimate, (immutable ? IMMUTABLE : 0));
        }

        @Override
        protected NodeSpliterator> newSubSpliterator(Node>[] array, int pos, int limit, int sizeEstimate) {
            return new ValueSpliterator<>(array, pos, limit, sizeEstimate, hasCharacteristics(IMMUTABLE));
        }

        @Override
        protected V apply(EntryNode entry) {
            return entry.getValue();
        }

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy