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

org.elasticsearch.common.collect.ImmutableOpenMap Maven / Gradle / Ivy

There is a newer version: 8.14.0
Show newest version
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

package org.elasticsearch.common.collect;

import com.carrotsearch.hppc.ObjectCollection;
import com.carrotsearch.hppc.ObjectContainer;
import com.carrotsearch.hppc.ObjectLookupContainer;
import com.carrotsearch.hppc.ObjectObjectAssociativeContainer;
import com.carrotsearch.hppc.ObjectObjectHashMap;
import com.carrotsearch.hppc.ObjectObjectMap;
import com.carrotsearch.hppc.cursors.ObjectCursor;
import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
import com.carrotsearch.hppc.predicates.ObjectObjectPredicate;
import com.carrotsearch.hppc.predicates.ObjectPredicate;
import com.carrotsearch.hppc.procedures.ObjectObjectProcedure;

import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * An immutable map implementation based on open hash map.
 * 

* Can be constructed using a {@link #builder()}, or using {@link #builder(ImmutableOpenMap)} (which is an optimized * option to copy over existing content and modify it). */ public final class ImmutableOpenMap implements Iterable> { private final ObjectObjectHashMap map; private ImmutableOpenMap(ObjectObjectHashMap map) { this.map = map; } /** * @return Returns the value associated with the given key or the default value * for the key type, if the key is not associated with any value. *

* Important note: For primitive type values, the value returned for a non-existing * key may not be the default value of the primitive type (it may be any value previously * assigned to that slot). */ public VType get(KType key) { return map.get(key); } /** * @return Returns the value associated with the given key or the provided default value if the * key is not associated with any value. */ public VType getOrDefault(KType key, VType defaultValue) { return map.getOrDefault(key, defaultValue); } /** * Returns true if this container has an association to a value for * the given key. */ public boolean containsKey(KType key) { return map.containsKey(key); } /** * @return Returns the current size (number of assigned keys) in the container. */ public int size() { return map.size(); } /** * @return Return true if this hash map contains no assigned keys. */ public boolean isEmpty() { return map.isEmpty(); } /** * Returns a cursor over the entries (key-value pairs) in this map. The iterator is * implemented as a cursor and it returns the same cursor instance on every * call to {@link Iterator#next()}. To read the current key and value use the cursor's * public fields. An example is shown below. *

     * for (IntShortCursor c : intShortMap)
     * {
     *     System.out.println("index=" + c.index
     *       + " key=" + c.key
     *       + " value=" + c.value);
     * }
     * 
*

* The index field inside the cursor gives the internal index inside * the container's implementation. The interpretation of this index depends on * to the container. */ @Override public Iterator> iterator() { return map.iterator(); } /** * Returns a specialized view of the keys of this associated container. * The view additionally implements {@link ObjectLookupContainer}. */ public ObjectLookupContainer keys() { return map.keys(); } /** * Returns a direct iterator over the keys. */ public Iterator keysIt() { final Iterator> iterator = map.keys().iterator(); return new Iterator() { @Override public boolean hasNext() { return iterator.hasNext(); } @Override public KType next() { return iterator.next().value; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } /** * Returns a {@link Set} view of the keys contained in this map. */ public Set keySet() { return new AbstractSet() { @Override public Iterator iterator() { return keysIt(); } @Override public int size() { return map.size(); } @Override @SuppressWarnings("unchecked") public boolean contains(Object o) { return map.containsKey((KType) o); } }; } /** * Returns a direct iterator over the keys. */ public Iterator valuesIt() { return iterator(map.values()); } /** * Returns a {@link Collection} view of the values contained in the map. */ public Collection values() { return new AbstractCollection() { @Override public Iterator iterator() { return valuesIt(); } @Override public int size() { return map.size(); } }; } static Iterator iterator(ObjectCollection collection) { final Iterator> iterator = collection.iterator(); return new Iterator() { @Override public boolean hasNext() { return iterator.hasNext(); } @Override public T next() { return iterator.next().value; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } /** * Returns a sequential unordered stream of the map entries. * * @return a {@link Stream} of the map entries as {@link Map.Entry} */ public Stream> stream() { final Iterator> mapIterator = map.iterator(); return StreamSupport.stream( new Spliterators.AbstractSpliterator>(map.size(), Spliterator.SIZED | Spliterator.DISTINCT) { @Override public boolean tryAdvance(Consumer> action) { if (mapIterator.hasNext() == false) { return false; } ObjectObjectCursor cursor = mapIterator.next(); action.accept(new AbstractMap.SimpleImmutableEntry<>(cursor.key, cursor.value)); return true; } }, false ); } @Override public String toString() { return map.toString(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @SuppressWarnings("rawtypes") ImmutableOpenMap that = (ImmutableOpenMap) o; if (map.equals(that.map) == false) return false; return true; } @Override public int hashCode() { return map.hashCode(); } @SuppressWarnings({ "unchecked", "rawtypes" }) private static final ImmutableOpenMap EMPTY = new ImmutableOpenMap(new ObjectObjectHashMap()); @SuppressWarnings("unchecked") public static ImmutableOpenMap of() { return EMPTY; } /** * @return An immutable copy of the given map */ public static ImmutableOpenMap copyOf(ObjectObjectMap map) { Builder builder = builder(); builder.putAll(map); return builder.build(); } public static Builder builder() { return new Builder<>(); } public static Builder builder(int size) { return new Builder<>(size); } public static Builder builder(ImmutableOpenMap map) { return new Builder<>(map); } public static class Builder implements ObjectObjectMap { private ObjectObjectHashMap map; @SuppressWarnings("unchecked") public Builder() { this(EMPTY); } public Builder(int size) { this.map = new ObjectObjectHashMap<>(size); } public Builder(ImmutableOpenMap map) { this.map = map.map.clone(); } /** * Builds a new instance of the */ public ImmutableOpenMap build() { ObjectObjectHashMap map = this.map; this.map = null; // nullify the map, so any operation post build will fail! (hackish, but safest) return map.isEmpty() ? of() : new ImmutableOpenMap<>(map); } /** * Puts all the entries in the map to the builder. */ public Builder putAll(Map map) { for (Map.Entry entry : map.entrySet()) { this.map.put(entry.getKey(), entry.getValue()); } return this; } /** * A put operation that can be used in the fluent pattern. */ public Builder fPut(KType key, VType value) { map.put(key, value); return this; } @Override public VType put(KType key, VType value) { return map.put(key, value); } @Override public VType get(KType key) { return map.get(key); } @Override public VType getOrDefault(KType kType, VType vType) { return map.getOrDefault(kType, vType); } @Override public int putAll(ObjectObjectAssociativeContainer container) { return map.putAll(container); } @Override public int putAll(Iterable> iterable) { return map.putAll(iterable); } /** * Remove that can be used in the fluent pattern. */ public Builder fRemove(KType key) { map.remove(key); return this; } @Override public VType remove(KType key) { return map.remove(key); } @Override public Iterator> iterator() { return map.iterator(); } @Override public boolean containsKey(KType key) { return map.containsKey(key); } @Override public int size() { return map.size(); } @Override public boolean isEmpty() { return map.isEmpty(); } @Override public int removeAll(ObjectContainer container) { return map.removeAll(container); } @Override public int removeAll(ObjectPredicate predicate) { return map.removeAll(predicate); } @Override public > T forEach(T procedure) { return map.forEach(procedure); } @Override public void clear() { map.clear(); } @Override public ObjectCollection keys() { return map.keys(); } @Override public ObjectContainer values() { return map.values(); } @SuppressWarnings("unchecked") public Builder cast() { return (Builder) this; } @Override public int removeAll(ObjectObjectPredicate predicate) { return map.removeAll(predicate); } @Override public > T forEach(T predicate) { return map.forEach(predicate); } @Override public int indexOf(KType key) { return map.indexOf(key); } @Override public boolean indexExists(int index) { return map.indexExists(index); } @Override public VType indexGet(int index) { return map.indexGet(index); } @Override public VType indexReplace(int index, VType newValue) { return map.indexReplace(index, newValue); } @Override public void indexInsert(int index, KType key, VType value) { map.indexInsert(index, key, value); } @Override public void release() { map.release(); } @Override public String visualizeKeyDistribution(int characters) { return map.visualizeKeyDistribution(characters); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy