GVKun编程网logo

ConcurrentHashMap.newKeySet()与Collections.newSetFromMap()

11

在本文中,我们将给您介绍关于ConcurrentHashMap.newKeySet的详细内容,并且为您解答与Collections.newSetFromMap的相关问题,此外,我们还将为您提供关于Ar

在本文中,我们将给您介绍关于ConcurrentHashMap.newKeySet的详细内容,并且为您解答与Collections.newSetFromMap的相关问题,此外,我们还将为您提供关于Arrays.asList()与Collections.singletonList()、Collections.emptyMap()与新的HashMap()、Collections.newSetFromMap(Map map)、Collectors.toConcurrentMap和通过Collectors.toMap供应商选项将地图转换为ConcurrentHashMap有什么区别?的知识。

本文目录一览:

ConcurrentHashMap.newKeySet()与Collections.newSetFromMap()

ConcurrentHashMap.newKeySet()与Collections.newSetFromMap()

Java 8引入了获取并发Set实现的新方法

// Pre-Java-8 way to create a concurrent setSet<String> oldStyle = Collections.newSetFromMap(new ConcurrentHashMap<>());// New method in Java 8Set<String> newStyle = ConcurrentHashMap.newKeySet();

有什么理由喜欢新方法吗?

有什么优点/缺点吗?

答案1

小编典典

ConcurrentHashMap.newKeySet()应该会更有效,因为它删除了一个间接级别。Collections.newSetFromMap(map)主要基于将操作重定向到map.keySet(),但ConcurrentHashMap.newKeySet()map.keySet()自身非常接近(仅在具有附加支持的情况下)。

至于功能,我认为没有区别。

Arrays.asList()与Collections.singletonList()

Arrays.asList()与Collections.singletonList()

使用Arrays.asList(something)优于Collections.singletonList(something)来构成包含一项的列表是否有优势(或有很大不同)?后者使返回的列表也不可变。

答案1

小编典典

Collections.singletonList(something)不可变的,
而数组Arrays.asList(something)是固定大小的List表示形式,列表和数组在堆中连接在一起。

Arrays.asList(something)允许对其进行 非结构更改 ,这些 更改 将同时反映到List和联合数组中。
UnsupportedOperationException 尽管您可以为特定索引设置元素,但它会添加,删除元素。

对返回的列表所做的任何更改Collections.singletonList(something)都会导致
UnsupportedOperationException

同样,返回的列表的容量Collections.singletonList(something)将始终为
1,这Arrays.asList(something)与其后备阵列的容量不同。

Collections.emptyMap()与新的HashMap()

Collections.emptyMap()与新的HashMap()

我可以使用哪些情况Collections.emptyMap()?文档说,如果我希望我的收藏集是不可变的,则可以使用此方法。

为什么我要一个不变的空集合? 有什么意义?

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

Collections.newSetFromMap(Map 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保证了它的并发性。




Collectors.toConcurrentMap和通过Collectors.toMap供应商选项将地图转换为ConcurrentHashMap有什么区别?

Collectors.toConcurrentMap和通过Collectors.toMap供应商选项将地图转换为ConcurrentHashMap有什么区别?

我想通过Java 8 和接口将a Map转换为ConcurrentHashMapvia ,我可以使用两个选项。Stream``Collector

首先:

Map<Integer,String> mb = persons.stream()
                                 .collect(Collectors.toMap(
                                            p -> p.age,p -> p.name,(name1,name2) -> name1+";"+name2,ConcurrentHashMap::new));

第二个:

Map<Integer,String> mb1 = persons.stream()
                                  .collect(Collectors.toConcurrentMap(
                                             p -> p.age,p -> p.name));

哪个是更好的选择?什么时候应该使用每个选项?

关于ConcurrentHashMap.newKeySet与Collections.newSetFromMap的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Arrays.asList()与Collections.singletonList()、Collections.emptyMap()与新的HashMap()、Collections.newSetFromMap(Map map)、Collectors.toConcurrentMap和通过Collectors.toMap供应商选项将地图转换为ConcurrentHashMap有什么区别?等相关知识的信息别忘了在本站进行查找喔。

本文标签: