package de.axone.data.weighted; import java.util.Collection; import java.util.Comparator; import java.util.EnumSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collector; import java.util.stream.Stream; public interface WeightedCollectionContained<W extends WeightedCollectionContained<W, T>, T> extends Iterable<WeightedCollectionContained.WeightedItem<T>>{ public W supply(); public W add( T item, double weight ); public W addAll( Iterable<WeightedItem<T>> items ); public W addAll( Stream<WeightedItem<T>> items ); public W addAllIf( Iterable<WeightedItem<T>> items, Predicate<T> filter ); public boolean contains( T item ); public int size(); public double weight(); public double maxWeight(); public double avgWeight(); public Set<WeightedItem<T>> asSet(); public List<WeightedItem<T>> asList(); public Stream<WeightedItem<T>> stream(); public Stream<WeightedItem<T>> sortedStream( Comparator<T> comparator ); public Stream<WeightedItem<T>> bestStream(); public W best( int amount ); public List<WeightedItem<T>> shuffled(); public List<WeightedItem<T>> shuffledStable(); public W overrideBy( W other ); public interface WeightedItem<I> { public I item(); public double weight(); public double normalized(); } public static class Impl<T> extends AbstractWeightedCollectionContained<Impl<T>,T> { public Impl( Supplier<Impl<T>> supplier ) { super( supplier ); } } public static class ItemCollector<T,X extends AbstractWeightedCollectionContained<X,T>> implements Collector<WeightedItem<T>,List<WeightedItem<T>>,X> { public ItemCollector( Supplier<X> supplier ) { this.supplier = supplier; } private final Supplier<X> supplier; @Override public Supplier<List<WeightedItem<T>>> supplier() { return LinkedList::new; } @Override public BiConsumer<List<WeightedItem<T>>, WeightedItem<T>> accumulator() { return Collection::add; } @Override public BinaryOperator<List<WeightedItem<T>>> combiner() { return (list1,list2) -> { list1.addAll( list2 ); return list1; }; } @Override public Function<List<WeightedItem<T>>, X> finisher() { return list -> { X impl = supplier.get(); impl.addAll( list ); return impl; }; } @Override public Set<Collector.Characteristics> characteristics() { return EnumSet.of( Collector.Characteristics.UNORDERED ); } } /* @FunctionalInterface public interface WeightedItemSupplier<T> { WeightedItem<T> get( T item, double value ); } */ @FunctionalInterface public interface Mapper<T,S> { public T map( S source ); } public class ConvertingWrapper<T, S> implements WeightedItem<T> { private final WeightedItem<S> source; private final Mapper<T,S> mapper; public ConvertingWrapper( WeightedItem<S> source, Mapper<T,S> mapper ) { this.source = source; this.mapper = mapper; } @Override public T item() { return mapper.map( source.item() ); } @Override public double weight() { return source.weight(); } @Override public double normalized() { return source.normalized(); } } public class TransportWrapper<T, S> implements WeightedItem<T> { private final S source; private final Mapper<T,S> mapper; public TransportWrapper( S source, Mapper<T,S> mapper ) { this.source = source; this.mapper = mapper; } @Override public T item() { return mapper.map( source ); } @Override public double weight() { return 1; } @Override public double normalized() { return 1; } } }