一、码出高效:
集合是开发中需要修改最多的地方,如:从数据库中取出多条数据是 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,再转为SetSet 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