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()
的话那插件就会在代码下报黄线提示你这是代码坏味道,建议优化。后面我就发现了使用Collections
的singleton
的一系列方法创建单个元素集合使用:
- 创建一个元素的Set:
Set<T> singleton(T o)
- 创建一个元素的List:
List<T> singletonList(T o)
- 创建一个元素的Map:
Map<K, V> singletonMap(K key, V value)
PS:创建出来的都是
singleton
源码片段:
代码语言:javascript复制/**
* 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();
错误。
singletonList
这是最简单并且推荐的方法,可以在其中「创建不可变List
的单个元素」。用这个方法创建的列表也是「不可变」的,所以你确定在任何情况下列表中不会有更多的元素。
Collections.singletonList()
返回的List
的容量始终是为**1
**,要是对其进行任何更改操作也将会导致报出UnsupportedOperationException
错误
源码片段:
代码语言:javascript复制/**
* 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
,创建出来的列表是「可变」的。
singletonMap
代码语言:javascript复制Collections.singletonMap(key, value)
Map<KeyType, ValueType> map = new HashMap<KeyType, ValueType>();
map.put(key, value);
当你只有一个键/值对时,使用singletonMap
更好,减少了不少代码。划重点:「只有一个键/值对时」
源码片段:
代码语言:javascript复制/**
* 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
方法是把参数与属性元素直接对比。