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

org.aksw.commons.collections.FeatureMapImpl Maven / Gradle / Ivy

There is a newer version: 0.9.9
Show newest version
package org.aksw.commons.collections;

import java.util.AbstractCollection;
import java.util.AbstractMap.SimpleEntry;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;

/**
 * Map a set of features to a single value.
 *
 * In
 *
 * @author raven
 *
 * @param 
 * @param 
 */
public class FeatureMapImpl
    extends AbstractCollection, V>>
    //extends AbstractMultimap
    implements FeatureMap
{
    // This map contains the actual data, the other fields contain helper structures

    protected Map tagToCount;

    protected Multimap> tagToTagSets;


    // Maybe the following two maps could be replaced with BiHashMultimap

    protected Multimap, V> tagSetToValues; // rename to tagSetToValues
    protected Multimap> valueToTagSets;



//    public ContainmentMapImpl(Map tagToCount,
//            Multimap> tagToTagSets,
//            Multimap, V> tagSetToValues,
//            Multimap> valueToTagSets) {
//        super();
//        this.tagToCount = tagToCount;
//        this.tagToTagSets = tagToTagSets;
//        this.tagSetToValues = tagSetToValues;
//        this.valueToTagSets = valueToTagSets;
//    }
    public FeatureMapImpl() {
        super();
        this.tagToCount = new HashMap<>();
        this.tagToTagSets = HashMultimap.create();
        this.tagSetToValues = HashMultimap.create();
        this.valueToTagSets = HashMultimap.create();
    }

    @Override
    public Set> keySet() {
        Set> result = tagSetToValues.keySet();
        return result;
    }

    @Override
    public Collection values() {
        Collection result = tagSetToValues.values();
        return result;
    }

    @Override
    public Set,Collection>> entrySet() {
        Set, Collection>> result = tagSetToValues.asMap().entrySet();
        return result;
    };

    @Override
    public void put(Set tagSet, V value) {
        //tagSetToValues.asMap().
        tagSetToValues.put(tagSet, value);
        tagSet.forEach(tag -> {
            tagToTagSets.put(tag, tagSet);
            tagToCount.merge(tag, 1, Integer::sum);
        });

        valueToTagSets.put(value, tagSet);

        //return value;
    }

    @Override
    public boolean remove(Object value) {
        @SuppressWarnings("unchecked")
        Collection> tagSets = valueToTagSets.get((V)value);

        tagSets.forEach(tagSet -> {
            tagSet.forEach(tag -> tagToCount.merge(tag, 1, (a, b) -> a - b));
        });

        return true;
    }

    /**
     * Return every entry of this featureMap whose associated feature set
     * is a super set of the given one.
     *
     */
    @Override
    public Collection, V>> getIfSupersetOf(Set prototype) {
        //Set, Set>> result;

        K leastUsedTag = prototype
            .stream()
            .map(k -> new SimpleEntry<>(k, tagToCount.getOrDefault(k, 0)))
            .min((a, b) -> a.getValue() - b.getValue())
            .map(Entry::getKey)
            .orElse(null);

        //Stream> baseStream;
        Stream, V>> baseStream;
        if(leastUsedTag != null) {
            Collection> rawTagSets = tagToTagSets.get(leastUsedTag);
            baseStream = rawTagSets
                    .stream()
                    .filter(tagSet -> tagSet.containsAll(prototype))
                    .flatMap(tagSet -> {
                        Collection v = tagSetToValues.get(tagSet);

                        Stream, V>> r = v.stream()
                            .map(w -> new SimpleEntry<>(tagSet, w));

                        return r;
                    });

        } else {
            //baseStream = tagToTagSets.values().stream();
            baseStream = tagSetToValues.entries().stream();
                    //.map(v -> new SimpleEntry<>(Collections.emptySet(), v));
            //baseStream = Stream.of(Collections.emptySet());
        }

//        Stream, V>> taggedStream = baseStream
//                .flatMap(tagSet -> {
//                    Collection v = tagSetToValues.get(tagSet);
//
//                    Stream, V>> r = v.stream()
//                        .map(w -> new SimpleEntry<>(tagSet, w));
//
//                    return r;
//                });

        Collection, V>> result = baseStream.collect(Collectors.toList());
        return result;
    }


    @Override
    public Collection, V>> getIfSubsetOf(Set prototype) {
        // get the count if we used index lookup
        int indexCount = prototype.isEmpty() ? Integer.MAX_VALUE : prototype.stream().mapToInt(tag -> tagToCount.getOrDefault(tag, 0)).sum();
        int totalCount = valueToTagSets.size();

        Stream> tagSetStream;
//        float scanThreshold = 0.3f;
//        float val = scanThreshold * totalCount;
//        if(indexCount > val) {
        boolean useScan = indexCount >= totalCount;
        if(useScan) {
            // perform a scan
            tagSetStream = tagSetToValues.keySet().stream();
        } else {
            tagSetStream = Stream.concat(
    				Stream.of(Collections.emptySet()),
    				prototype.stream()
    					.flatMap(tag -> tagToTagSets.get(tag).stream())
    					.distinct());
        }

        Collection, V>> result = tagSetStream
            .filter(tagSet -> prototype.containsAll(tagSet))
            .flatMap(tagSet -> {
                Collection values = tagSetToValues.get(tagSet);
                Stream, V>> r = values.stream()
                        .map(w -> new SimpleEntry<>(tagSet, w));
                return r;
            })
            .collect(Collectors.toSet());

        return result;
    }

    @Override
    public String toString() {
        return "FeatureMapImpl [tagToCount=" + tagToCount
                + ", tagToTagSets=" + tagToTagSets + ", tagSetToValues="
                + tagSetToValues + ", valueToTagSets=" + valueToTagSets + "]";
    }

    @Override
    public Iterator, V>> iterator() {
        Iterator, V>> result = tagSetToValues.entries().iterator();
        return result;
    }

    @Override
    public int size() {
        int result = tagSetToValues.size();
        return result;
    }

	@Override
	public Collection get(Set prototype) {
		//Collection result = Collections.unmodifiableCollection(tagSetToValues.get(prototype));
		Collection result = tagSetToValues.get(prototype);
		return result;
	}


	@Override
	public boolean removeValue(Object v) {
		Set> tagSets = getTagSets(v);
		boolean result = remove(tagSets);
		return result;
	}

	@Override
	public Set> getTagSets(Object v) {
		@SuppressWarnings("unchecked")
		Set> result = SetUtils.asSet(valueToTagSets.get((V)v));
		return result;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy