Collections.newSetFromMap(Map<E,Boolean> map)

Collections提供了一种保证元素唯一性的Map实现,就是用一个Set来表示Map,它持有这个Map的引用,并且保持Map的顺序、并发和性能特征。这就是newSetFromMap方法:

public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {

        return new SetFromMap<>(map);
}
从Collections中可以看到,这里使用了一个内部类SetFromMap,它实现了Set接口。使用方法就是将Map的实例作为构造参数传入构造方法,并且这个Map必须是空的,否则抛出非法参数的异常:
SetFromMap(Map<E, Boolean> map) {
            if (!map.isEmpty())
                throw new IllegalArgumentException("Map is non-empty");
            m = map;
            s = map.keySet();
}
一般的最佳实践是,用一个空的Map传入构造方法,比如:
Set<Object> weakHashSet = Collections.newSetFromMap(new WeakHashMap<Object, Boolean>());
Set中的值就用Map的key来存储。用Map的put方法来add,就是这样:
 public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }
这里的m就是持有的Map。又因为addAll的实现是多次调用add方法,因为在这里就是多次调用m.put,而addAll在Collections中已经实现了。因此addAll是唯一一个继承的方法。具体的内部类定义见下:
private static class SetFromMap<E> extends AbstractSet<E>
        implements Set<E>, Serializable
    {
        private final Map<E, Boolean> m;  // The backing map
        private transient Set<E> s;       // Its keySet


        SetFromMap(Map<E, Boolean> map) {
            if (!map.isEmpty())
                throw new IllegalArgumentException("Map is non-empty");
            m = map;
            s = map.keySet();
        }


        public void clear()               {        m.clear(); }
        public int size()                 { return m.size(); }
        public boolean isEmpty()          { return m.isEmpty(); }
        public boolean contains(Object o) { return m.containsKey(o); }
        public boolean remove(Object o)   { return m.remove(o) != null; }
        public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }
        public Iterator<E> iterator()     { return s.iterator(); }
        public Object[] toArray()         { return s.toArray(); }
        public <T> T[] toArray(T[] a)     { return s.toArray(a); }
        public String toString()          { return s.toString(); }
        public int hashCode()             { return s.hashCode(); }
        public boolean equals(Object o)   { return o == this || s.equals(o); }
        public boolean containsAll(Collection<?> c) {return s.containsAll(c);}
        public boolean removeAll(Collection<?> c)   {return s.removeAll(c);}
        public boolean retainAll(Collection<?> c)   {return s.retainAll(c);}
        // addAll is the only inherited implementation


        private static final long serialVersionUID = 2454657854757543876L;


        private void readObject(java.io.ObjectInputStream stream)
            throws IOException, ClassNotFoundException
        {
            stream.defaultReadObject();
            s = m.keySet();
        }
    }
--------------------------------------------应用实例------------------------------------------------
在spring framework中AbstractBeanFactory中使用了一个名为alreadyCreated的Set来存放已经定义过得bean的名字。它的定义如下:
         private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(64));
因为java中没有ConcurrentSet这种东西,而从逻辑上讲又应当使用一个Set来实现,因此这里就使用了上面所说的方法。它是一个SetFromMap的实例。这样,既保持了alreadyCreated作为一个Set变量的逻辑意义,又通过传入的ConcurrentHashMap保证了它的并发性。




转载于:https://my.oschina.net/RoseMaiden/blog/182381

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值