org.aksw.commons.collections.FeatureMapImpl Maven / Gradle / Ivy
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