〔啤酒〕满怀忧思,不如先干再说!做干净纯粹的技术分享!欢迎评论区或私信交流! 本文记录一下数组和集合相互转换的几种方法和一些坑,自己总结的同时也分享给有缘人,希望在工作和面试的时候有所帮助,集合和数组的作用区别就不废话了,直接进入正文!共识 首先要达成的共识:数组可以存储任意类型的数据,包括基本数据类型和引用数据类型【也就是对象】而集合虽然可以扩展大小,但是只能存储对象并不能存储基本数据类型 所以在使用集合存储整数,字符,小数时需要使用对应的包装类 不禁问一下初学Java的小朋友,String是基本数据类型吗?〔狗头〕〔白眼〕 接下来就是,数组和集合相互转换的具体实现和常见BUG的复现和解决! 数组转集合asList基本数据类型数组问题 在java。util。Arrays这个JDK提供的工具类中有一个asList方法,可以将数组转换为一个集合声明数组Integer〔〕arr{1,2,3,4,5};转换集合ListIntegerlistArrays。asList(arr);遍历数组for(IntegerarrResult:arr){System。out。println(arrResult);}遍历集合for(IntegerlistResult:list){System。out。println(listResult);} 上边的数组是引用数据类型,转换时没一点问题, 但是当数组是基本数据类型时就会出现bug了,如下方代码,转换前数组长度为5,转换后长度变为1声明数组,基本数据类型int〔〕arr{1,2,3,4,5};转换集合,此时的泛型编译器自动识别为【int〔〕】类型Listint〔〕listArrays。asList(arr);原数组长度为5System。out。println(arr。length);转换后的集合大小大小为1System。out。println(list。size()); 这个问题原因通过看asList源码可以了解到publicstaticTListTasList(T。。。a){returnnewArrayList(a);} 此处发现asList方法接收一个泛型变长参数,而基本数据类型不能泛型化,只有对象可以泛型化,如果想让基本数据类型泛型化必须使用其包装类,如果使用基本数据类型的数组通过asList转换,则直接将数组当做一个数据塞进了集合中,所以得到的集合大小为1。 不仅仅int有这样的问题,其他的7个基本数据类型都有该问题,使用时一定注意!asList转换的集合不能添加和删除元素 下方代码将学生数组转换为集合声明数组String〔〕students{石昊,石毅,月禅,火灵儿};转换为集合ListStringlistArrays。asList(students);向集合中添加数据list。add(石中天); 对集合进行add或者remove方法就会出现非法操作异常 根据上边asList源码发现,是newArrayList返回,问题就在于创建的ArrayList并不是java。util包中的,而是Arrays工具类中的内部类 和java。util。ArrayList相同继承了java。util。AbstractList这个抽象类,而该抽象类中的add方法默认返回异常 java。util。ArrayList:重写了add,remove等方法,所以可以添加数据Arrays。ArrayList:并没有重写,调用时依旧可以调用,但是就会抛出异常 下方为Arrays。ArrayList内部类部分源码privatestaticclassArrayListEextendsAbstractListEimplementsRandomAccess,java。io。Serializable{privatestaticfinallongserialVersionUID2764017481108945198L;数组privatefinalE〔〕a;构造方法ArrayList(E〔〕array){aObjects。requireNonNull(array);}获取长度Overridepublicintsize(){returna。}转换为数组OverridepublicObject〔〕toArray(){returna。clone();}OverrideSuppressWarnings(unchecked)publicTT〔〕toArray(T〔〕a){intsizesize();if(a。lengthsize)returnArrays。copyOf(this。a,size,(C?extendsT〔〕)a。getClass());System。arraycopy(this。a,0,a,0,size);if(a。lengthsize)a〔size〕}OverridepublicEget(intindex){returna〔index〕;}OverridepublicEset(intindex,Eelement){EoldValuea〔index〕;a〔index〕returnoldV}OverridepublicintindexOf(Objecto){E〔〕athis。a;if(onull){for(inti0;ia。i)if(a〔i〕null)}else{for(inti0;ia。i)if(o。equals(a〔i〕))}return1;}Overridepublicbooleancontains(Objecto){returnindexOf(o)!1;}OverridepublicSpliteratorEspliterator(){returnSpliterators。spliterator(a,Spliterator。ORDERED);}OverridepublicvoidforEach(C?superEaction){Objects。requireNonNull(action);for(Ee:a){action。accept(e);}}OverridepublicvoidreplaceAll(UnaryOperatorEoperator){Objects。requireNonNull(operator);E〔〕athis。a;for(inti0;ia。i){a〔i〕operator。apply(a〔i〕);}}Overridepublicvoidsort(C?superEc){Arrays。sort(a,c);}} 由此看出其实asList返回的是一个长度不可变的List,数组多长,返回的List也就多大,仅仅是包了一个外壳,并不支持扩容,新增数据和删除数据等操作,如果将这个List通过方法调用传递到一个要add和removeList的方法中就会产生意想不到的结果。 这可以认为是Java设计上的一个缺陷,使用时一定要注意! 如果你确定这个集合只读,而不会做修改操作,则可以放心使用,但是如果拿捏不准,就需要其装进java。util包下的ArrayList中,转换成真正的ArrayList,以免出现不可预料的结果声明数组String〔〕students{石昊,石毅,月禅,火灵儿};转换为集合ListStringlistArrays。asList(students);放进java。util的ArrayList中ListStringrealListnewArrayList(list);向集合中添加数据realList。add(石中天);for(Strings:realList){System。out。println(s);}通过Collections。addAll转换声明数组String〔〕students{石昊,石毅,月禅,火灵儿};创建集合ArrayListStringlistnewArrayList();Collections。addAll(list,students);list。add(石中天);for(Strings:list){System。out。println(s);} 此处创建java。util。ArrayList,可以继续进行add和remove等操作,但是不能将基本数据类型的数组转换为集合通过JDK8的流操作 此处可以使用boxed()方法将基本数据类型的数组转换成包装类,非常方便声明数组int〔〕arr{1,2,3,4};ListIntegerlistArrays。stream(arr)。boxed()。collect(Collectors。toList());list。add(5);for(Integerresult:list){System。out。println(result);}集合转数组 通过集合对象的toArray方法返回Object类型数组Object〔〕toArray();返回指定类型数组TT〔〕toArray(T〔〕a); 将Integer集合转换为Integer类型数组,这里的数组也必须是包装类声明数组ListIntegerlistnewArrayList();list。add(1);list。add(2);list。add(3);list。add(4);Integer〔〕arraylist。toArray(newInteger〔list。size()〕);for(Integerresult:array){System。out。println(result);} 这就是数组和集合之间转换的几种常见方式和隐患,尤其是asList一定不要被坑了 希望可以帮助你少走一些弯路,节约一些时间,解决一些实质问题,更多干货可持续关注〔啤酒〕