首页 > 编程语言 >编程规约-处理Map List Set

编程规约-处理Map List Set

时间:2022-09-23 17:24:14浏览次数:54  
标签:Map Set ArrayList List add 集合 new null

编程规约-处理Map List Set

Map

Collectors 类的 toMap()方法 相同键相关联的值之间的冲突

在使用 java.util.stream.Collectors 类的 toMap()方法转为 Map 集合时,一定要使用含有参数类型为 BinaryOperator,参数名为 mergeFunction 的方法,否则当出现相同 key值时会抛出 IllegalStateException 异常。

toMap(Function<? super T,? extends K> keyMapper,
    Function<? super T,? extends U> valueMapper,
    BinaryOperator<U> mergeFunction)

参数

keyMapper - 产生密钥的映射函数

valueMapper - 产生值的映射函数

mergeFunction - 一个合并函数,用于解决与相同键相关联的值之间的冲突,提供给 Map.merge(Object, Object, BiFunction)

说明:参数 mergeFunction 的作用是当出现 key 重复时,自定义对 value 的处理策略。

正例:

List<Pair<String, Double>> pairArrayList = new ArrayList<>(3);
pairArrayList.add(new Pair<>("version", 12.10));
pairArrayList.add(new Pair<>("version", 12.19));
pairArrayList.add(new Pair<>("version", 6.28));
Map<String, Double> map = pairArrayList.stream().collect(
    // 生成的 map 集合中只有一个键值对:{version=6.28}
    Collectors.toMap(Pair::getKey, Pair::getValue, (v1, v2) -> v2));

反例:

String[] departments = new String[]{"iERP", "iERP", "EIBU"};
// 抛出 IllegalStateException 异常
Map<Integer, String> map = Arrays.stream(departments).collect(
    Collectors.toMap(String::hashCode, str -> str));

Collectors 类的 toMap()方法 value 为 null 时会抛 空指针异常

在使用 java.util.stream.Collectors 类的 toMap()方法转为 Map 集合时,一定要注意当 value 为 null 时会抛 空指针异常。

说明:在 java.util.HashMap 的 merge 方法里会进行如下的判断:

if (value == null || remappingFunction == null) {
    throw new NullPointerException();
}

反例:

List<Pair<String, Double>> pairArrayList = new ArrayList<>(2);
pairArrayList.add(new Pair<>("version1", 8.3));
pairArrayList.add(new Pair<>("version2", null));
Map<String, Double> map = pairArrayList.stream().collect(
    // 抛出 NullPointerException 异常
    Collectors.toMap(Pair::getKey, Pair::getValue, (v1, v2) -> v2));

使用 Map 的方法 keySet()/values()/entrySet()返回的集合对象

使用 Map 的方法 keySet()/values()/entrySet()返回集合对象时,不可以对其进行添加元素操作,否则会抛出 UnsupportedOperationException 异常。

使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。

说明:keySet 其实是遍历了 2 次,一次是转为 Iterator 对象,另一次是从 hashMap 中取出 key 所对应的 value。而 entrySet 只是遍历了一次就把 key 和 value 都放到了 entry 中,效率更高。如果是 JDK8,使用 Map.forEach 方法。

正例:values() 返回的是 V 值集合,是一个 list 集合对象;keySet()返回的是 K 值集合,是一个 Set 集合对象;entrySet()返回的是 K-V 值组合集合。

高度注意 Map 类集合 K/V 能不能存储 null 值的情况

线程安全【key 不允许为 null,Value 不允许为 null】:

  1. Hashtable:key 不允许为 null,Value 不允许为 null,父类 Dictionary。

  2. ConcurrentHashMap:key 不允许为 null,Value 不允许为 null,父类 AbstractMap,锁分段技术(JDK8:CAS)。

线程不安全【value 允许为 null】:

  1. HashMap:key 允许为 null,value 允许为 null,父类 AbstractMap。

  2. TreeMap:key 不允许为 null,value 允许为 null,父类 AbstractMap。

反例:由于 HashMap 的干扰,很多人认为 ConcurrentHashMap 是可以置入 null 值,而事实上,存储 null 值时会抛出 NPE 异常。

List

ArrayList 的 subList 结果不可强转成 ArrayList

ArrayList 的 subList 结果不可强转成 ArrayList,否则会抛出 ClassCastException 异常:java.util.RandomAccessSubList cannot be cast to java.util.ArrayList。

说明:subList()返回的是 ArrayList 的内部类 SubList,并不是 ArrayList 本身,而是 ArrayList 的一个视图,对于 SubList 的所有操作最终会反映到原列表上。

在 subList 场景中,注意对父集合元素的增加或删除

在 subList 场景中,高度注意对父集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生 ConcurrentModificationException 异常。

使用集合转数组的方法

使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一致、长度为 0 的空数组。

反例:直接使用 toArray 无参方法存在问题,此方法返回值只能是 Object[]类,若强转其它类型数组将出现 ClassCastException 错误。

正例:

List<String> list = new ArrayList<>(2);
list.add("guan");
list.add("bao");
String[] array = list.toArray(new String[0]);

说明:使用 toArray 带参方法,数组空间大小的 length:

  1. 等于 0,动态创建与 size 相同的数组,性能最好。

  2. 大于 0 但小于 size,重新创建大小等于 size 的数组,增加 GC 负担。

  3. 等于 size,在高并发情况下,数组创建完成之后,size 正在变大的情况下,负面影响与2 相同。

  4. 大于 size,空间浪费,且在 size 处插入 null 值,存在 NPE 隐患。

使用工具类 Arrays.asList()把数组转换成集合

使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。

说明:asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList 体现的是适配器模式,只是转换接口,后台的数据仍是数组。

String[] str = new String[]{ "chen", "yang", "hao" };
List list = Arrays.asList(str);

第一种情况:list.add("yangguanbao"); 运行时异常。

第二种情况:str[0] = "change"; list 也会随之修改。

Arrays.ArrayList 源码

        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }

Set

利用 Set 元素唯一的特性

利用 Set 元素唯一的特性,可以快速对一个集合进行去重操作,避免使用 List 的

contains()进行遍历去重或者判断包含操作。

标签:Map,Set,ArrayList,List,add,集合,new,null
From: https://www.cnblogs.com/gcbeen/p/16723446.html

相关文章