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

io.helidon.grpc.core.WeightedBag Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2019, 2024 Oracle and/or its affiliates.
 *
 * 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 io.helidon.grpc.core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import java.util.stream.Stream;

import io.helidon.common.Weight;
import io.helidon.common.Weighted;

/**
 * A bag of values ordered by weight. All weights must be greater or equal to 0.
 * 

* The higher the weight the higher the priority. For cases where the weight is the same, * elements are returned in the order that they were added to the bag. * * @param the type of elements in the bag * @see io.helidon.common.Weight */ public class WeightedBag implements Iterable { private final Map> contents; private final double defaultWeight; private WeightedBag(Map> contents, double defaultWeight) { this.contents = contents; if (defaultWeight < 0.0) { throw new IllegalArgumentException("Weights must be greater or equal to 0"); } this.defaultWeight = defaultWeight; } /** * Create a new {@link WeightedBag} where elements added with no weight will be * given a default weight of 0. * * @param the type of elements in the bag * @return a new {@link WeightedBag} where elements added * with no weight will be given {@link Weighted#DEFAULT_WEIGHT} */ public static WeightedBag create() { return create(Weighted.DEFAULT_WEIGHT); } /** * Create a new {@link WeightedBag} where elements added with no weight will be * given a default weight of 0. * * @param defaultWeight default weight for elements * @param the type of elements in the bag * @return a new {@link WeightedBag} where elements added * with no weight will be given {@link Weighted#DEFAULT_WEIGHT} */ public static WeightedBag create(double defaultWeight) { return new WeightedBag<>(new TreeMap<>( (o1, o2) -> Double.compare(o2, o1)), // reversed for weights defaultWeight); } /** * Check if bag is empty. * * @return outcome of test */ public boolean isEmpty() { return contents.isEmpty(); } /** * Obtain an immutable copy of this {@link WeightedBag}. * * @return an immutable copy of this {@link WeightedBag} */ public WeightedBag readOnly() { return new WeightedBag<>(Collections.unmodifiableMap(contents), defaultWeight); } /** * Merge a {@link WeightedBag} into this {@link WeightedBag}. * * @param bag the bag to merge */ public void merge(WeightedBag bag) { bag.contents.forEach((weight, value) -> addAll(value, weight)); } /** * Obtain a copy of this {@link WeightedBag}. * * @return a copy of this {@link WeightedBag} */ public WeightedBag copyMe() { WeightedBag copy = WeightedBag.create(); copy.merge(this); return copy; } /** * Add elements to the bag. *

* If the element's class is annotated with the {@link io.helidon.common.Weight} * annotation then that value will be used to determine weight otherwise the * default weight value will be used. * * @param values the elements to add */ public void addAll(Iterable values) { for (T value : values) { add(value); } } /** * Add elements to the bag with a given weight. * * @param values the elements to add * @param weight the weight to assign to the elements */ public void addAll(Iterable values, double weight) { for (T value : values) { add(value, weight); } } /** * Add an element to the bag. *

* If the element's class is annotated with the {@link io.helidon.common.Weight} * annotation then that value will be used to determine weight otherwise the * default weight value will be used. * * @param value the element to add */ public void add(T value) { Objects.requireNonNull(value); double weight; if (value instanceof Weighted weighted) { weight = weighted.weight(); } else { Weight annotation = value.getClass().getAnnotation(Weight.class); weight = (annotation == null) ? defaultWeight : annotation.value(); } add(value, weight); } /** * Add an element to the bag with a specific weight. * * @param value the element to add * @param weight the weight of the element */ public void add(T value, double weight) { Objects.requireNonNull(value); if (weight < 0.0) { throw new IllegalArgumentException("Weights must be greater or equal to 0"); } contents.compute(weight, (key, list) -> { List newList = list; if (newList == null) { newList = new ArrayList<>(); } newList.add(value); return newList; }); } /** * Obtain the contents of this {@link WeightedBag} as * an ordered {@link Stream}. * * @return the contents of this {@link WeightedBag} as * an ordered {@link Stream} */ public Stream stream() { return contents.entrySet() .stream() .flatMap(e -> e.getValue().stream()); } @Override public Iterator iterator() { return stream().iterator(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy