Java 番石榴:一套<;K>+;功能<;K、 V>;=地图<;K、 V>;?

Java 番石榴:一套<;K>+;功能<;K、 V>;=地图<;K、 V>;?,java,collections,guava,Java,Collections,Guava,是否有一种惯用的方法来获取集合和函数,并获得地图实时视图?(即映射由集合和函数组合支持,如果例如一个元素被添加到集合,则相应的条目也存在于映射中) (有关实时视图的更多讨论,请参见示例) 如果不需要实时视图怎么办?还有比这更好的吗 public static <K,V> Map<K,V> newMapFrom(Set<K> keys, Function<? super K,V> f) { Map<K,V> map = Maps

是否有一种惯用的方法来获取
集合
函数
,并获得
地图
实时视图?(即
映射
集合
函数
组合支持,如果例如一个元素被添加到
集合
,则相应的条目也存在于
映射
中)

(有关实时视图的更多讨论,请参见示例)


如果不需要实时视图怎么办?还有比这更好的吗

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;
}
publicstaticmap newMapFrom(Set键,函数Guava14现在用于查看集合和不可变副本

您可以在此处看到有关问题的大部分讨论:

我不知道这是否就是你所说的“实时查看”的意思。无论如何,这是我的尝试

public class GuavaTst {
public static void main(String[] args) {
    final Function<String, String> functionToLower = new Function<String, String>() {
        public String apply (String input) {
            return input.toLowerCase();
        }
    };

      final Set<String> set=new HashSet<String>();
      set.add("Hello");
      set.add("BYE");
      set.add("gOOd");
      Map<String, String> testMap = newLiveMap(set,functionToLower);
      System.out.println("Map :- "+testMap);
      System.out.println("Set :- "+set);
      set.add("WoRld");
      System.out.println("Map :- "+testMap);
      System.out.println("Set :- "+set);
      testMap.put("OMG","");
      System.out.println("Map :- "+testMap);
      System.out.println("Set :- "+set);

 }


 static <K,V> Map<K,V> newLiveMap(final Set<K> backEnd,final Function<K,V> fun)
 {
    return new HashMap<K,V>(){


            @Override
            public void clear() {

                backEnd.clear();
            }
            @Override
            public boolean containsKey(Object key) {

                return backEnd.contains(key);
            }
            @Override
            public boolean isEmpty() {

                return backEnd.isEmpty();
            }
            @Override
            public V put(K key, V value) {

                backEnd.add(key);
                return null; 
            }
            @Override
            public boolean containsValue(Object value) {

                for(K s:backEnd)
                    if(fun.apply(s).equals(value))
                        return true;
                return false;
            }
            @Override
            public V remove(Object key) {

                backEnd.remove(key);
                return null;
            }
            @Override
            public int size() {

                return backEnd.size();
            }

            @Override
            public V get(Object key) {

                return fun.apply((K)key);
            }
            @Override
            public String toString() {

                StringBuilder b=new StringBuilder();
                Iterator<K> itr=backEnd.iterator();

                b.append("{");
                if(itr.hasNext())
                {
                 K key=itr.next();  
                 b.append(key);
                 b.append(":");
                 b.append(this.get(key));

                 while(itr.hasNext())
                 {
                  key=itr.next();
                  b.append(", ");
                  b.append(key);
                  b.append(":");
                  b.append(this.get(key));   
                 }
                }

                b.append("}");

                return b.toString();
            }
        };              
 } 
}
从集合和函数创建映射 这里有两个类,每个类都应该完成这项工作。第一个类仅显示集合的映射视图,而第二个类可以通过特殊接口将值写回集合

调用语法:

public interface SetFunctionMap<K,V> extends Map<K, V>{
     public boolean putKey(K key);
     public boolean removeKey(K key);
}
public class SetBackedMapTst {
public static void main(String[] args) {
    Set<Integer> set=new TreeSet<Integer>(Arrays.asList(
            1, 2, 4, 8, 16));
    final SetFunctionMap<Integer, String> map =
        new SetBackedMap<Integer, String>(set,
            new Function<Integer, String>(){
                @Override
                public String apply(final Integer from){
                    return Integer.toBinaryString(from.intValue());
                }
            });
          set.add(222);
          System.out.println("Map: "+map); 
          System.out.println("Set: "+set);
          map.putKey(112);
          System.out.println("Map: "+map); 
          System.out.println("Set: "+set);
          map.removeKey(112);
          System.out.println("Map: "+map); 
          System.out.println("Set: "+set);

}
}
Map: {1=1, 2=10, 4=100, 8=1000, 16=10000, 222=11011110}//change to set reflected in map 
Set: [1, 2, 4, 8, 16, 222]
Map: {1=1, 2=10, 4=100, 8=1000, 16=10000, 112=1110000, 222=11011110}
Set: [1, 2, 4, 8, 16, 112, 222]//change to map reflected in set 
Map: {1=1, 2=10, 4=100, 8=1000, 16=10000, 222=11011110}
Set: [1, 2, 4, 8, 16, 222]//change to map reflected in set 
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);
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
public interface ComputingMap<K, V> extends Map<K, V>{
    boolean removeKey(final K key);
    boolean addKey(final K key);
}
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}
测试:

public interface SetFunctionMap<K,V> extends Map<K, V>{
     public boolean putKey(K key);
     public boolean removeKey(K key);
}
public class SetBackedMapTst {
public static void main(String[] args) {
    Set<Integer> set=new TreeSet<Integer>(Arrays.asList(
            1, 2, 4, 8, 16));
    final SetFunctionMap<Integer, String> map =
        new SetBackedMap<Integer, String>(set,
            new Function<Integer, String>(){
                @Override
                public String apply(final Integer from){
                    return Integer.toBinaryString(from.intValue());
                }
            });
          set.add(222);
          System.out.println("Map: "+map); 
          System.out.println("Set: "+set);
          map.putKey(112);
          System.out.println("Map: "+map); 
          System.out.println("Set: "+set);
          map.removeKey(112);
          System.out.println("Map: "+map); 
          System.out.println("Set: "+set);

}
}
Map: {1=1, 2=10, 4=100, 8=1000, 16=10000, 222=11011110}//change to set reflected in map 
Set: [1, 2, 4, 8, 16, 222]
Map: {1=1, 2=10, 4=100, 8=1000, 16=10000, 112=1110000, 222=11011110}
Set: [1, 2, 4, 8, 16, 112, 222]//change to map reflected in set 
Map: {1=1, 2=10, 4=100, 8=1000, 16=10000, 222=11011110}
Set: [1, 2, 4, 8, 16, 222]//change to map reflected in set 
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);
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
public interface ComputingMap<K, V> extends Map<K, V>{
    boolean removeKey(final K key);
    boolean addKey(final K key);
}
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}

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

地图界面:

public interface SetFunctionMap<K,V> extends Map<K, V>{
     public boolean putKey(K key);
     public boolean removeKey(K key);
}
public class SetBackedMapTst {
public static void main(String[] args) {
    Set<Integer> set=new TreeSet<Integer>(Arrays.asList(
            1, 2, 4, 8, 16));
    final SetFunctionMap<Integer, String> map =
        new SetBackedMap<Integer, String>(set,
            new Function<Integer, String>(){
                @Override
                public String apply(final Integer from){
                    return Integer.toBinaryString(from.intValue());
                }
            });
          set.add(222);
          System.out.println("Map: "+map); 
          System.out.println("Set: "+set);
          map.putKey(112);
          System.out.println("Map: "+map); 
          System.out.println("Set: "+set);
          map.removeKey(112);
          System.out.println("Map: "+map); 
          System.out.println("Set: "+set);

}
}
Map: {1=1, 2=10, 4=100, 8=1000, 16=10000, 222=11011110}//change to set reflected in map 
Set: [1, 2, 4, 8, 16, 222]
Map: {1=1, 2=10, 4=100, 8=1000, 16=10000, 112=1110000, 222=11011110}
Set: [1, 2, 4, 8, 16, 112, 222]//change to map reflected in set 
Map: {1=1, 2=10, 4=100, 8=1000, 16=10000, 222=11011110}
Set: [1, 2, 4, 8, 16, 222]//change to map reflected in set 
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);
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
public interface ComputingMap<K, V> extends Map<K, V>{
    boolean removeKey(final K key);
    boolean addKey(final K key);
}
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}

对于非实时视图,代码以
Lambda.map(Set,Converter)
的形式存在

Set setKs=new Set();
转换器KV=新转换器{
@凌驾
公共V转换(K从){
return null;//在这里不有用,但是您可以做任何您想做的事情
}
}
Map mapKvs=Lambda.Map(setKs,converterKv);
我尝试了自己的实现: 正如在评论中所说,我必须扩展另一个类,所以我刚刚实现了
Map
,这就是为什么有这么多代码


有一个完全无用的(或没有?)功能,允许您在运行中更改转换器。

关于

的注意事项。肖恩·帕特里克·弗洛伊德(Sean Patrick Floyd)的答案虽然非常有用,但也有一个缺陷。一个简单的例子,但我花了一段时间进行调试,所以不要落入同一个陷阱:MapEntry类需要equals和hashcode实现。这是我的(来自javadoc的简单副本)

@覆盖
公共布尔等于(对象obj){
如果(!(obj输入实例)){
返回false;
}
条目e2=(条目)obj;
返回(getKey()==null?e2.getKey()==null:getKey().equals(e2.getKey()))
&&(getValue()==null?e2.getValue()==null:getValue().equals(e2.getValue());
}
@凌驾
公共int hashCode(){
返回值(getKey()==null?0:getKey().hashCode())^
(getValue()==null?0:getValue().hashCode());
}


作为对相关答案的评论,这个回复会更好,但是我没有权利发表评论(或者找不到如何发表评论!)

你所说的“实时查看”是什么意思?啊,听起来它可能非常有用。使用Maps可能会稍有改进。newHashMapWithExpectedSize(keys.size())还有
Maps.transformEntries()
,这是活的,但不是正确的签名。番石榴现在以
地图的形式提供。asMap
…我只想将
最终函数funk
更改为
最终函数Function@Colin是的,但是它必须是
最终的Function@seanizer:我认为如果可以覆盖toString,这很好,所以你可以直接打印地图。@Emil显然,但是
hashCode()
equals()
toString()
已经由
AbstractMap
@seanizer提供了。@seanizer:实际上我的意思是,如果我们可以像这样打印地图是好的{1:1,2:10,4:100…},而不是[1,2,4..]这是toStringAnd的当前输出,已经有两年了,所以不要期望它很快发生……不,不是很快,但看起来它最终会出现在Guava 14中(在@Beta)。@seanizer:手动是指函数put(键,值)?但是这个函数不起作用。它抛出不受支持的异常。所以映射密钥的唯一方法就是使用这个函数。我误解了你。等几分钟,我正在寻找一个更好的答案。这是倒退。OP希望计算值,而不是键。+1:事实上,根据
Map.Entry
的约定,这两种方法是必需的。(而且你目前没有StackOverflow的“声誉”来发表评论。通过写好答案,你可以提高“声誉”并解锁该网站的许多功能。)我花了3年时间才看到这个答案:-)当然是这样,但作为一个一般的经验法则:在上面看到的任何代码都不应该被视为一个完整的生产就绪解决方案,即使它有时包含有价值的想法。