gpt4 book ai didi

java - Guava :Set + Function = Map

转载 作者:IT老高 更新时间:2023-10-28 20:57:22 36 4
gpt4 key购买 nike

有没有一种惯用的方法来获取 Set<K>Function<K,V> ,并获得 Map<K,V>实时取景? (即 MapSetFunction 组合支持,例如,如果将元素添加到 Set ,则相应的条目也存在于 Map 中。

(参见例如 Collections2.filter 了解更多关于实时取景的讨论)


如果不需要实时取景怎么办?还有比这更好的吗:

public static <K,V> Map<K,V> newMapFrom(Set<K> keys, Function<? super K,V> f) {
Map<K,V> map = Maps.newHashMap();
for (K k : keys) {
map.put(k, f.apply(k));
}
return map;
}

最佳答案

从集合和函数创建映射

这里有两个类应该各自完成这项工作。第一个只是显示集合的 map View ,而第二个可以通过特殊接口(interface)将值写回集合。

调用语法:

Map<K,V> immutable = new SetBackedMap<K,V>(Set<K> keys, Function<K,V> func);
Map<K,V> mutable = new MutableSetBackedMap<K,V>(Set<K> keys, Function<K,V> func);

把这段代码放在哪里?

旁注:如果 Guava 是我的图书馆,我会通过 Maps 让它们访问。类:

Map<K,V> immutable = Maps.immutableComputingMap(Set<K> keys, Function<K,V> func);
Map<K,V> mutable = Maps.mutableComputingMap(Set<K> keys, Function<K,V> func);

不可变版本:

我已将其实现为单向 View :

  • 对集合的更改反射(reflect)在映射,但反之则不行(无论如何您都无法更改映射,put(key, value) 方法未实现)。
  • entrySet() 迭代器使用在内部设置迭代器,因此它将也继承了内部迭代器的处理ConcurrentModificationException.
  • put(k,v)entrySet().iterator().remove() 将扔UnsupportedOperationException.
  • 值缓存在 WeakHashMap 中,没有特殊的并发处理,即没有同步任何级别。这适用于大多数情况,但如果您的功能很昂贵,您可能需要添加一些锁定。

代码:

public class SetBackedMap<K, V> extends AbstractMap<K, V>{

private class MapEntry implements Entry<K, V>{
private final K key;
public MapEntry(final K key){
this.key = key;
}
@Override
public K getKey(){
return this.key;
}
@Override
public V getValue(){
V value = SetBackedMap.this.cache.get(this.key);
if(value == null){
value = SetBackedMap.this.funk.apply(this.key);
SetBackedMap.this.cache.put(this.key, value);
}
return value;
}
@Override
public V setValue(final V value){
throw new UnsupportedOperationException();
}
}

private class EntrySet extends AbstractSet<Entry<K, V>>{

public class EntryIterator implements Iterator<Entry<K, V>>{
private final Iterator<K> inner;
public EntryIterator(){
this.inner = EntrySet.this.keys.iterator();
}
@Override
public boolean hasNext(){
return this.inner.hasNext();
}
@Override
public Map.Entry<K, V> next(){
final K key = this.inner.next();
return new MapEntry(key);
}
@Override
public void remove(){
throw new UnsupportedOperationException();
}
}

private final Set<K> keys;

public EntrySet(final Set<K> keys){
this.keys = keys;
}

@Override
public Iterator<Map.Entry<K, V>> iterator(){
return new EntryIterator();
}

@Override
public int size(){
return this.keys.size();
}

}

private final WeakHashMap<K, V> cache;
private final Set<Entry<K, V>> entries;
private final Function<? super K, ? extends V> funk;

public SetBackedMap(
final Set<K> keys, Function<? super K, ? extends V> funk){
this.funk = funk;
this.cache = new WeakHashMap<K, V>();
this.entries = new EntrySet(keys);
}

@Override
public Set<Map.Entry<K, V>> entrySet(){
return this.entries;
}

}

测试:

final Map<Integer, String> map =
new SetBackedMap<Integer, String>(
new TreeSet<Integer>(Arrays.asList(
1, 2, 4, 8, 16, 32, 64, 128, 256)),
new Function<Integer, String>(){

@Override
public String apply(final Integer from){
return Integer.toBinaryString(from.intValue());
}
});
for(final Map.Entry<Integer, String> entry : map.entrySet()){
System.out.println(
"Key: " + entry.getKey()
+ ", value: " + entry.getValue());
}

输出:

Key: 1, value: 1
Key: 2, value: 10
Key: 4, value: 100
Key: 8, value: 1000
Key: 16, value: 10000
Key: 32, value: 100000
Key: 64, value: 1000000
Key: 128, value: 10000000
Key: 256, value: 100000000

可变版本:

虽然我认为单向是一个好主意,但这里有一个 Emil 版本,它提供了双向 View (它是 Emil 对我的解决方案的变体的一种变体 :-))。它需要一个扩展的 map 接口(interface),我将调用 ComputingMap 以明确这是一个调用 put(key, value) 没有意义的 map 。

map 界面:

public interface ComputingMap<K, V> extends Map<K, V>{
boolean removeKey(final K key);
boolean addKey(final K key);
}

map 实现:

public class MutableSetBackedMap<K, V> extends AbstractMap<K, V> implements
ComputingMap<K, V>{

public class MapEntry implements Entry<K, V>{

private final K key;

public MapEntry(final K key){
this.key = key;
}

@Override
public K getKey(){
return this.key;
}

@Override
public V getValue(){
V value = MutableSetBackedMap.this.cache.get(this.key);
if(value == null){
value = MutableSetBackedMap.this.funk.apply(this.key);
MutableSetBackedMap.this.cache.put(this.key, value);
}
return value;
}

@Override
public V setValue(final V value){
throw new UnsupportedOperationException();
}

}

public class EntrySet extends AbstractSet<Entry<K, V>>{

public class EntryIterator implements Iterator<Entry<K, V>>{

private final Iterator<K> inner;

public EntryIterator(){
this.inner = MutableSetBackedMap.this.keys.iterator();
}

@Override
public boolean hasNext(){
return this.inner.hasNext();
}

@Override
public Map.Entry<K, V> next(){
final K key = this.inner.next();
return new MapEntry(key);
}

@Override
public void remove(){
throw new UnsupportedOperationException();
}

}

public EntrySet(){
}

@Override
public Iterator<Map.Entry<K, V>> iterator(){
return new EntryIterator();
}

@Override
public int size(){
return MutableSetBackedMap.this.keys.size();
}

}

private final WeakHashMap<K, V> cache;
private final Set<Entry<K, V>> entries;
private final Function<? super K, ? extends V> funk;
private final Set<K> keys;

public MutableSetBackedMap(final Set<K> keys,
final Function<? super K, ? extends V> funk){
this.keys = keys;
this.funk = funk;
this.cache = new WeakHashMap<K, V>();
this.entries = new EntrySet();
}

@Override
public boolean addKey(final K key){
return this.keys.add(key);
}

@Override
public boolean removeKey(final K key){
return this.keys.remove(key);
}

@Override
public Set<Map.Entry<K, V>> entrySet(){
return this.entries;
}

}

测试:

public static void main(final String[] args){
final ComputingMap<Integer, String> map =
new MutableSetBackedMap<Integer, String>(
new TreeSet<Integer>(Arrays.asList(
1, 2, 4, 8, 16, 32, 64, 128, 256)),
new Function<Integer, String>(){

@Override
public String apply(final Integer from){
return Integer.toBinaryString(from.intValue());
}
});
System.out.println(map);
map.addKey(3);
map.addKey(217);
map.removeKey(8);
System.out.println(map);
}

输出:

{1=1, 2=10, 4=100, 8=1000, 16=10000, 32=100000, 64=1000000, 128=10000000, 256=100000000}
{1=1, 2=10, 3=11, 4=100, 16=10000, 32=100000, 64=1000000, 128=10000000, 217=11011001, 256=100000000}

关于java - Guava :Set<K> + Function<K,V> = Map<K,V>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3869258/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com