是否存在已知键的 java 映射实现,但仅应在第一次访问时计算值,因为计算值的成本很高。
下面演示了我希望它如何工作。
someMap.keySet(); // Returns all keys but no values are computed.
someMap.get(key); // Returns the value for key computing it if needed.
原因是我有一些东西保存了一堆数据,并且这个对象将数据返回为 Map<String, String>
这计算量很大,因为计算值的成本很高,但计算键的成本却很低。
map 必须保持其类型,因此我无法返回 Map<String, Supplier<String>>
。返回的Map
可能会以只读方式返回。
map 本身可以通过传入 Set<String>
来创建。定义键和 Function<String, String>
给定一个键返回它的值。
最佳答案
一个解决方案可能是拥有一个接受一组键的Set
的Map和一个给定键可以计算值的Function
。
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
/**
* Create a Map where we already know the keys but computing the values is expensive and so is delayed as
* much as possible.
*
*/
@AllArgsConstructor
public class MapWithValuesProvidedByFunction implements Map<String, String> {
/**
* All keys that are defined.
*/
private Set<String> keys;
/**
* A function which maps a key to its value.
*/
private Function<String, String> mappingFunction;
/**
* Holds all keys and values we have already computed.
*/
private final Map<String, String> computedValues = new HashMap<>();
@Override
public int size() {
return keys.size();
}
@Override
public boolean isEmpty() {
return keys.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return keys.contains(key);
}
@Override
public boolean containsValue(Object value) {
if(computedValues.size() == keys.size()) return computedValues.containsValue(value);
for(String k : keys) {
String v = get(k);
if(v == value) return true;
if(v != null && v.equals(value)) return true;
}
return false;
}
@Override
public String get(Object key) {
if(keys.contains(key)) {
return computedValues.computeIfAbsent(key.toString(), mappingFunction);
}
return null;
}
@Override
public String put(String key, String value) {
throw new UnsupportedOperationException("Not modifiable");
}
@Override
public String remove(Object key) {
throw new UnsupportedOperationException("Not modifiable");
}
@Override
public void putAll(Map<? extends String, ? extends String> m) {
throw new UnsupportedOperationException("Not modifiable");
}
@Override
public void clear() {
throw new UnsupportedOperationException("Not modifiable");
}
@Override
public Set<String> keySet() {
return Collections.unmodifiableSet(keys);
}
@Override
public Collection<String> values() {
return keys.stream().map(this::get).collect(Collectors.toList());
}
@Override
public Set<java.util.Map.Entry<String, String>> entrySet() {
Set<Entry<String, String>> set = new HashSet<>();
for(String s : keys) {
set.add(new MyEntry(s, this::get));
}
return set;
}
@AllArgsConstructor
@EqualsAndHashCode
public class MyEntry implements Entry<String, String> {
private String key;
private Function<String, String> valueSupplier;
@Override
public String getKey() {
return key;
}
@Override
public String getValue() {
return valueSupplier.apply(key);
}
@Override
public String setValue(String value) {
throw new UnsupportedOperationException("Not modifiable");
}
}
}
使用的示例可能是:
Map<String, String> map = new MapWithValuesProvidedByFunction(
Set.of("a", "b", "c"), // The known keys
k -> "Slow to compute function"); // The function to make the values
将其更改为通用应该很容易。
我怀疑存在更好的解决方案,但这对其他人来说可能已经足够好了。
关于java - 一个java映射,其中键是已知的,但值应该稍后计算,因为它们很昂贵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60217387/