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

org.apache.bookkeeper.util.collections.SynchronizedHashMultiMap Maven / Gradle / Ivy

There is a newer version: 4.17.1
Show newest version
/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.bookkeeper.util.collections;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiPredicate;
import org.apache.commons.lang3.tuple.Pair;
/**
 * Simple multimap implementation that only stores key reference once.
 *
 * 

Implementation is aimed at storing PerChannelBookieClient completions when there * are duplicates. If the key is a pooled object, it must not exist once the value * has been removed from the map, which can happen with guava multimap implemenations. * *

With this map is implemented with pretty heavy locking, but this shouldn't be an * issue as the multimap only needs to be used in rare cases, i.e. when a user tries * to read or the same entry twice at the same time. This class should *NOT* be used * in critical path code. * *

A unique key-value pair will only be stored once. */ public class SynchronizedHashMultiMap { HashMap>> map = new HashMap<>(); public synchronized void put(K k, V v) { map.computeIfAbsent(k.hashCode(), (ignore) -> new HashSet<>()).add(Pair.of(k, v)); } public synchronized Optional getAnyKey() { return map.values().stream().findAny().flatMap(pairs -> pairs.stream().findAny().map(p -> p.getLeft())); } public synchronized Optional removeAny(K k) { Set> set = map.getOrDefault(k.hashCode(), Collections.emptySet()); Optional> pair = set.stream().filter(p -> p.getLeft().equals(k)).findAny(); pair.ifPresent(p -> set.remove(p)); return pair.map(p -> p.getRight()); } public synchronized int removeIf(BiPredicate predicate) { int removedSum = map.values().stream().mapToInt( pairs -> { int removed = 0; // Can't use removeIf because we need the count Iterator> iter = pairs.iterator(); while (iter.hasNext()) { Pair kv = iter.next(); if (predicate.test(kv.getLeft(), kv.getRight())) { iter.remove(); removed++; } } return removed; }).sum(); map.values().removeIf((s) -> s.isEmpty()); return removedSum; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy