java集合常见的错误

本文详细介绍了Java开发中关于ArrayList的subList和toArray方法的使用规则,强调了它们的特性以及在操作过程中可能出现的异常,同时提到了如何正确地进行数组和集合之间的转换,以提升代码质量和避免常见错误。
摘要由CSDN通过智能技术生成

一、码出高效:
集合是开发中需要修改最多的地方,如:从数据库中取出多条数据是 List 结构,然后需要在 Service 进行层层处理,最终为前端展示提供 vo 对象,所以,很多集合使用的规范一定要弄明白。

代码的字里行间流淌的是软件系统的血液,质量的提升是尽可能少踩坑,杜绝踩重复的坑,切实提升系统稳定性,码出质量。

强制】ArrayList 的 subList 结果不可强转成 ArrayList,否则会抛出 ClassCastException 异常;

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

强制】ArrayList 的 subList 场景中,高度注意对原集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生 ConcurrentModificationException 异常;

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

强制】使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一样的数组,大小就是 list.size();

说明

(1)使用 toArray 带参方法,入参分配的数组空间不够大时,toArray 方法内部将重新分配内存空间,并返回新数组地址。

(2)如果数组元素个数大于实际所需,下标为[ list.size() ]的数组元素将被置为null,其它数组元素保持原值,因此最好将方法入参数组大小定义与集合元素个数一致;
(3)而直接使用 toArray无参方法存在问题,此方法返回值只能是 Object[]类,若强转其它类型数组将出现 ClassCastException 错误。

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

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

  • 如果强行改变,如:list.add(“new”) 新元素,会抛出异常;
  • 如果改变数组元素,集合元素也会改变,如:str[0] = “change”,那么 list.get(0)也会随之修改。

【强制】不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator(迭代器)方式,如果是并发操作,需要对 Iterator 的对象加锁。

说明:for循环内,如果在直接使用 remove/add 操作,将对原集合的操作,势必改变集合结构,该结构的改变势必影响新一轮的遍历。

List<String> list = new ArrayList<>(); 
list.add("1"); 
list.add("2"); 
Iterator<String> iterator = list.iterator(); 
while (iterator.hasNext()) { 
    String item = iterator.next(); 
    if (删除元素的条件) { 
        iterator.remove(); 
    } 
}

解释都在【码出高效】里,干货都在【总结】里,这里直接上验证方法,可直接运行在 Junit 测试类中:

@Test
public void test_arr_list_set(){
    // Stream 是通过 Java 8 引入的方法,所以需要最低 Java 8 的支持
    String[] arr = new String[]{"jimmy","amy","simmy"};
    List<String> list = Stream.of("father","mather","baby").collect(Collectors.toList());
    Set<String> set = Stream.of("big","small","middle").collect(Collectors.toSet());
 
    /**  - - - - - - - - - - - - 数组、List 互转 - - - - - - - - - - - -  */
    // 1. 数组转List
    // 方法①:长度不可变,不可add,remove,否则会报java.lang.UnsupportedOpera
    // 常见问题见—— 验证①,验证②,验证③
    List<String> arrToList_1 = Arrays.asList(arr);
    // 方法①改进:长度灵活可变
    List<String> arrToList_2 = new ArrayList<>(Arrays.asList(arr));
    // 方法②:长度灵活可变
    List<String> arrToList_3 = new ArrayList<>();
    if (arr != null && arr.length > 0) {
        for (String tempStr : arr) {
            arrToList_3.add(tempStr);
        }
    }
    System.out.println("arrToList_1 = " + JSON.toJSONString(arrToList_1));
    System.out.println("arrToList_2 = " + JSON.toJSONString(arrToList_2));
    System.out.println("arrToList_3 = " + JSON.toJSONString(arrToList_3));
 
    // 2. List转数组:必须使用集合的 toArray(T[] array),传入的是类型完全一样的数组,大小就是 list.size()
    String[] listToArr = list.toArray(new String[list.size()]);
    System.out.println("listToArr = " + JSON.toJSONString(listToArr));
 
    /**  - - - - - - - - - - - - 数组、Set 互转 - - - - - - - - - - - -  */
    // 3. 数组转Set:需要先转为List,再转为Set
    Set arrToSet = new HashSet(Arrays.asList(arr));
    System.out.println("arrToSet = " + JSON.toJSONString(arrToSet));
 
    // 4. Set转数组
    String[] setToArr = set.toArray(new String[list.size()]);
    System.out.println("setToArr = " + JSON.toJSONString(setToArr));
 
    /**  - - - - - - - - - - - - List、Set 互转 - - - - - - - - - - - -  */
    // 5. List转Set:转换过程中要保证类型一致,否则会报类型转换异常(ClassCastException)
    Set<String> listToSet = new HashSet<>(list);
    System.out.println("listToSet = " + JSON.toJSONString(listToSet));
 
    // 6. Set转List:转换过程中要保证类型一致,否则会报类型转换异常(ClassCastException)
    List<String> setToList = new ArrayList(set);
    System.out.println("setToList = " + JSON.toJSONString(setToList));
 
    /**  - - - - - - - - - - - - 注意事项 + 验证 - - - - - - - - - - - -  */
    // 验证①:Arrays.asList(arr)下,str[0] = "jiming"; 那么 list.get(0)也会随之修改
    arr[0] = "jiming";
    System.out.println("arrToList_1_change = " + JSON.toJSONString(arrToList_1));
 
    // 验证②:ArrayList.subList()结果不可强转成ArrayList,否则会报类型转换异常(ClassCastException)
    // 说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList 而是 ArrayList 的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上
    List<String> subList = list.subList(0,2);
    System.out.println("subList = " + JSON.toJSONString(subList));
    subList.set(0, "honey");
    System.out.println("subList_change = " + JSON.toJSONString(subList));
    System.out.println("list_original = " + JSON.toJSONString(list));
 
    // 验证③: Arrays.asList(arr)下,不支持的操作异常(UnsupportedOperationException)
    try {
        arrToList_1.add("exception");
    } catch (Exception e) {
        System.out.println("e1 = " + JSON.toJSONString(e.getMessage()));
    }finally {
        System.out.println("arrToList_1_add = " + JSON.toJSONString(arrToList_1));
    }
    try {
        arrToList_2.add("exception");
    } catch (Exception e) {
        System.out.println("e2 = " + JSON.toJSONString(e.getMessage()));
    } finally {
        System.out.println("arrToList_2_add = " + JSON.toJSONString(arrToList_2));
    }
}

总结

  • 数组 转 List:长度不可变,用 Arrays.asList(arr),例:List arrToList = Arrays.asList(arr);需要长度可变,可使用 Arrays.asList(arr) 的改进方法,例:List arrToList = new ArrayList<>(Arrays.asList(arr));或者,新建 List 使用 foreach 遍历添加进去;
  • List 转 数组:必须使用集合的 toArray(T[] array),传入的是类型完全一样的数组,大小就是 list.size(),例:String[] listToArr = list.toArray(new String[list.size()]);
  • 数组 转 Set:需要先转为List,再转为Set,例:Set arrToSet = new HashSet(Arrays.asList(arr));
  • Set 转 数组:必须使用集合的 toArray(T[] array),传入的是类型完全一样的数组,大小就是 list.size(),例:String[] setToArr = set.toArray(new String[list.size()]);
  • List 转 Set:转换过程中要保证类型一致,例:Set listToSet = new HashSet<>(list);
  • Set 转 List:转换过程中要保证类型一致,例:List setToList = new ArrayList(set)。

原文链接:https://blog.csdn.net/weixin_44259720/article/details/110437544

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值