/* * Original work Copyright 2015 Real Logic Ltd. * Modified work Copyright (c) 2015, Hazelcast, Inc. All Rights Reserved. * * 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 com.hazelcast.util.collection; import com.hazelcast.util.function.Consumer; import java.util.Map; /** * Map that takes two part int key and associates with an object. * <p/> * The underlying implementation use as {@link Long2ObjectHashMap} and combines both int keys into a long key. * * @param <V> type of the object stored in the map. */ public class BiInt2ObjectMap<V> { @SuppressWarnings("checkstyle:magicnumber") private static final long LOWER_INT_MASK = (1L << Integer.SIZE) - 1; /** * Handler for a map entry * * @param <V> type of the value */ public interface EntryConsumer<V> { /** * A map entry * * @param keyPartA for the key * @param keyPartB for the key * @param value for the entry */ void accept(int keyPartA, int keyPartB, V value); } private final Long2ObjectHashMap<V> map; /** * Construct an empty map */ public BiInt2ObjectMap() { map = new Long2ObjectHashMap<V>(); } /** * See {@link Long2ObjectHashMap#Long2ObjectHashMap(int, double)}. * * @param initialCapacity for the underlying hash map * @param loadFactor for the underlying hash map */ public BiInt2ObjectMap(final int initialCapacity, final double loadFactor) { map = new Long2ObjectHashMap<V>(initialCapacity, loadFactor); } /** * Get the total capacity for the map to which the load factor with be a fraction of. * * @return the total capacity for the map. */ public int capacity() { return map.capacity(); } /** * Get the load factor beyond which the map will increase size. * * @return load factor for when the map should increase size. */ public double loadFactor() { return map.loadFactor(); } /** * Put a value into the map. * * @param keyPartA for the key * @param keyPartB for the key * @param value to put into the map * @return the previous value if found otherwise null */ public V put(final int keyPartA, final int keyPartB, final V value) { final long key = compoundKey(keyPartA, keyPartB); return map.put(key, value); } /** * Retrieve a value from the map. * * @param keyPartA for the key * @param keyPartB for the key * @return value matching the key if found or null if not found. */ public V get(final int keyPartA, final int keyPartB) { final long key = compoundKey(keyPartA, keyPartB); return map.get(key); } /** * Remove a value from the map and return the value. * * @param keyPartA for the key * @param keyPartB for the key * @return the previous value if found otherwise null */ public V remove(final int keyPartA, final int keyPartB) { final long key = compoundKey(keyPartA, keyPartB); return map.remove(key); } /** * Iterate over the entries of the map * * @param consumer to apply to each entry in the map */ public void forEach(final EntryConsumer<V> consumer) { for (Map.Entry<Long, V> entry : map.entrySet()) { Long compoundKey = entry.getKey(); final int keyPartA = (int) (compoundKey >>> Integer.SIZE); final int keyPartB = (int) (compoundKey & LOWER_INT_MASK); consumer.accept(keyPartA, keyPartB, entry.getValue()); } } /** * Iterate over the values in the map * * @param consumer to apply to each value in the map */ public void forEach(final Consumer<V> consumer) { for (Map.Entry<Long, V> entry : map.entrySet()) { consumer.accept(entry.getValue()); } } /** * Return the number of unique entries in the map. * * @return number of unique entries in the map. */ public int size() { return map.size(); } /** * Is map empty or not. * * @return boolean indicating empty map or not */ public boolean isEmpty() { return map.isEmpty(); } private static long compoundKey(final int keyPartA, final int keyPartB) { return ((long) keyPartA << Integer.SIZE) | keyPartB; } }