Collections的singleton,singletonList,singletonMap

Stella981
• 阅读 630

Collections的singleton,singletonList,singletonMap

今天记录一下在IDEA的sonarLint插件代码分析提示需要优化的代码:

//converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON_UTF8)); converter.setSupportedMediaTypes(Collections.singletonList(new MediaType("application", "json", StandardCharsets.UTF_8)));

这里只需要创建一个元素的List的时候用Arrays.asList()的话那插件就会在代码下报黄线提示你这是代码坏味道,建议优化。后面我就发现了使用Collectionssingleton的一系列方法创建单个元素集合使用:

  • 创建一个元素的Set: Set<T> singleton(T o)

  • 创建一个元素的List: List<T> singletonList(T o)

  • 创建一个元素的Map: Map<K, V> singletonMap(K key, V value)

PS:创建出来的都是

singleton

源码片段:

`/**
     * Returns an immutable set containing only the specified object.
     * 返回仅包含指定对象的不可变集合。
     * The returned set is serializable.
     * 返回的集合是可序列化的。
     *
     * @param   the class of the objects in the set
     * @param 集合中对象的类
     * @param o the sole object to be stored in the returned set.
     * @param o唯一要存储在返回集中的对象。
     * @return an immutable set containing only the specified object.
     * @返回一个仅包含指定对象的不可变集合。
     */
    public static  Set singleton(T o) {
        return new SingletonSet<>(o);
    }

 /**
     * @serial include
     * @序列包括
     */
    private static class SingletonSet
        extends AbstractSet
        implements Serializable {
        private static final long serialVersionUID = 3193687207550431679L;

        private final E element;

        SingletonSet(E e) {element = e;}

        public Iterator iterator() {
            return singletonIterator(element);
        }

        public int size() {return 1;}

        public boolean contains(Object o) {return eq(o, element);}

        // Override default methods for Collection
        //覆盖Collection的默认方法
        @Override
        public void forEach(Consumer<? super E> action) {
            action.accept(element);
        }
        @Override
        public Spliterator spliterator() {
            return singletonSpliterator(element);
        }
        @Override
        public boolean removeIf(Predicate<? super E> filter) {
            throw new UnsupportedOperationException();
        }
    }
`

源码注释可以看到Returns an immutable set containing only the specified object.(返回仅包含指定对象的不可变集合。),可以说明这个方法返回的Set集合是不可变的,要是对其进行任何更改操作将会导致报出throw new UnsupportedOperationException();错误。

singletonList

这是最简单并且推荐的方法,可以在其中「创建不可变List的单个元素」。用这个方法创建的列表也是「不可变」的,所以你确定在任何情况下列表中不会有更多的元素。

Collections.singletonList()返回的List的容量始终是为**1**,要是对其进行任何更改操作也将会导致报出UnsupportedOperationException错误

源码片段:

`/**
     * Returns an immutable list containing only the specified object.
     * 返回仅包含指定对象的不可变列表。
     * The returned list is serializable.
     * 返回的列表是可序列化的。
     *
     * @param   the class of the objects in the list
     * @param 列表中对象的类
     * @param o the sole object to be stored in the returned list.
     * @param是要存储在返回列表中的唯一对象。
     * @return an immutable list containing only the specified object.
     * @返回一个仅包含指定对象的不可变列表。
     * @since 1.3
     * @从1.3开始
     */
    public static  List singletonList(T o) {
        return new SingletonList<>(o);
    }

/**
     * @serial include
     * @序列包括
     */
    private static class SingletonList
        extends AbstractList
        implements RandomAccess, Serializable {

        private static final long serialVersionUID = 3093736618740652951L;

        private final E element;

        SingletonList(E obj)                {element = obj;}

        public Iterator iterator() {
            return singletonIterator(element);
        }

        public int size() {return 1;}

        public boolean contains(Object obj) {return eq(obj, element);}

        public E get(int index) {
            if (index != 0)
              throw new IndexOutOfBoundsException("Index: "+index+", Size: 1");
            return element;
        }

        // Override default methods for Collection
        //覆盖Collection的默认方法
        @Override
        public void forEach(Consumer<? super E> action) {
            action.accept(element);
        }
        @Override
        public boolean removeIf(Predicate<? super E> filter) {
            throw new UnsupportedOperationException();
        }
        @Override
        public void replaceAll(UnaryOperator operator) {
            throw new UnsupportedOperationException();
        }
        @Override
        public void sort(Comparator<? super E> c) {
        }
        @Override
        public Spliterator spliterator() {
            return singletonSpliterator(element);
        }
    }
`

PS:Array.asList()此方法也是快速创建List,创建出来的列表是「可变」的。

singletonMap

`Collections.singletonMap(key, value)

Map<KeyType, ValueType> map = new HashMap<KeyType, ValueType>();
map.put(key, value);
`

当你只有一个键/值对时,使用singletonMap更好,减少了不少代码。划重点:「只有一个键/值对时」

源码片段:

`/**
     * Returns an immutable map, mapping only the specified key to the
     * 返回一个不可变的映射,只将指定的键映射到
     * specified value.  The returned map is serializable.
     * 指定值返回的映射是可序列化的。
     *
     * @param  the class of the map keys
     * @param 映射键的类
     * @param  the class of the map values
     * @param map值的类别
     * @param key the sole key to be stored in the returned map.
     * @param键是要存储在返回地图中的唯一键。
     * @param value the value to which the returned map maps key.
     * @param value是返回的地图将key映射到的值。
     * @return an immutable map containing only the specified key-value mapping.
     * 返回一个只包含指定键-值映射的不可变映射。
     * @since 1.3
     * @从1.3开始
     */
    public static <K,V> Map<K,V> singletonMap(K key, V value) {
        return new SingletonMap<>(key, value);
    }

/**
     * @serial include
     * @序列包括
     */
    private static class SingletonMap<K,V>
          extends AbstractMap<K,V>
          implements Serializable {
        private static final long serialVersionUID = -6979724477215052911L;

        private final K k;
        private final V v;

        SingletonMap(K key, V value) {
            k = key;
            v = value;
        }

        public int size() {return 1;}
        public boolean isEmpty() {return false;}
        public boolean containsKey(Object key) {return eq(key, k);}
        public boolean containsValue(Object value) {return eq(value, v);}
        public V get(Object key) {return (eq(key, k) ? v : null);}

        private transient Set keySet;
        private transient Set<Map.Entry<K,V>> entrySet;
        private transient Collection values;

        public Set keySet() {
            if (keySet==null)
                keySet = singleton(k);
            return keySet;
        }

        public Set<Map.Entry<K,V>> entrySet() {
            if (entrySet==null)
                entrySet = Collections.<Map.Entry<K,V>>singleton(
                    new SimpleImmutableEntry<>(k, v));
            return entrySet;
        }

        public Collection values() {
            if (values==null)
                values = singleton(v);
            return values;
        }

        // Override default methods in Map
        // 覆盖Map中的默认方法
        @Override
        public V getOrDefault(Object key, V defaultValue) {
            return eq(key, k) ? v : defaultValue;
        }

        @Override
        public void forEach(BiConsumer<? super K, ? super V> action) {
            action.accept(k, v);
        }

        @Override
        public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
            throw new UnsupportedOperationException();
        }

        @Override
        public V putIfAbsent(K key, V value) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean remove(Object key, Object value) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean replace(K key, V oldValue, V newValue) {
            throw new UnsupportedOperationException();
        }

        @Override
        public V replace(K key, V value) {
            throw new UnsupportedOperationException();
        }

        @Override
        public V computeIfAbsent(K key,
                Function<? super K, ? extends V> mappingFunction) {
            throw new UnsupportedOperationException();
        }

        @Override
        public V computeIfPresent(K key,
                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
            throw new UnsupportedOperationException();
        }

        @Override
        public V compute(K key,
                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
            throw new UnsupportedOperationException();
        }

        @Override
        public V merge(K key, V value,
                BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
            throw new UnsupportedOperationException();
        }
    }
`

这三个内部类都是非常高效的

  • SingletonListSingletonSet 都用一个属性来表示拥有的元素,而不是用数组、列表来表示, SingletonMap 分别用两个属性表示 key/value,内存使用上更高效

  • 在方法的实现上也更高效,减少了循环。比如 size 方法都是直接返回 1 , List.contains 方法是把参数与属性元素直接对比。

本文分享自微信公众号 - 爱敲代码的猫(aquanrun)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这