今天记录一下在IDEA的 sonarLint
插件代码分析提示需要优化的代码:
//converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON_UTF8)); converter.setSupportedMediaTypes(Collections.singletonList(new MediaType("application", "json", StandardCharsets.UTF_8)));
这里只需要创建一个元素的 List
的时候用 Arrays.asList()
的话那插件就会在代码下报黄线提示你这是代码坏味道,建议优化。后面我就发现了使用 Collections
的 singleton
的一系列方法创建单个元素集合使用:
Set<T> singleton(T o) List<T> singletonList(T o) Map<K, V> singletonMap(K key, V value)
PS:创建出来的都是
源码片段:
/** * Returns an immutable set containing only the specified object. * 返回仅包含指定对象的不可变集合。 * The returned set is serializable. * 返回的集合是可序列化的。 * * @param <T> the class of the objects in the set * @param <T>集合中对象的类 * @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 <T> Set<T> singleton(T o) { return new SingletonSet<>(o); } /** * @serial include * @序列包括 */ private static class SingletonSet<E> extends AbstractSet<E> implements Serializable { private static final long serialVersionUID = 3193687207550431679L; private final E element; SingletonSet(E e) {element = e;} public Iterator<E> 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<E> 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();
错误。
这是最简单并且推荐的方法,可以在其中
创建不可变 List
的单个元素
。用这个方法创建的列表也是 不可变
的,所以你确定在任何情况下列表中不会有更多的元素。
Collections.singletonList()
返回的 List
的容量始终是为** 1
**,要是对其进行任何更改操作也将会导致报出 UnsupportedOperationException
错误
源码片段:
/** * Returns an immutable list containing only the specified object. * 返回仅包含指定对象的不可变列表。 * The returned list is serializable. * 返回的列表是可序列化的。 * * @param <T> the class of the objects in the list * @param <T>列表中对象的类 * @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 <T> List<T> singletonList(T o) { return new SingletonList<>(o); } /** * @serial include * @序列包括 */ private static class SingletonList<E> extends AbstractList<E> implements RandomAccess, Serializable { private static final long serialVersionUID = 3093736618740652951L; private final E element; SingletonList(E obj) {element = obj;} public Iterator<E> 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<E> operator) { throw new UnsupportedOperationException(); } @Override public void sort(Comparator<? super E> c) { } @Override public Spliterator<E> spliterator() { return singletonSpliterator(element); } }
PS: Array.asList()
此方法也是快速创建 List
,创建出来的列表是 可变
的。
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 <K> the class of the map keys * @param <K>映射键的类 * @param <V> the class of the map values * @param <V>map值的类别 * @param key the sole key to be stored in the returned map. * @param键是要存储在返回地图中的唯一键。 * @param value the value to which the returned map maps <tt>key</tt>. * @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<K> keySet; private transient Set<Map.Entry<K,V>> entrySet; private transient Collection<V> values; public Set<K> 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<V> 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(); } }
这三个内部类都是非常高效的
SingletonList
和 SingletonSet
都用一个属性来表示拥有的元素,而不是用数组、列表来表示, SingletonMap
分别用两个属性表示 key/value
,内存使用上更高效 size
方法都是直接返回 1 , List.contains
方法是把参数与属性元素直接对比。