深入理解List的toArray()方法和toArray(T[] a)方法
这两个方法都是将列表List中的元素转导出为数组,不同的是,toArray()方法导出的是Object类型数组,而toArray[T[] a]方法导出的是指定类型的数组。

下面是两个方法的申明及说明,摘自Java8的API文档。

toArray()方法
会返回List中所有元素构成的数组,并且数组类型是Object[]。还要注意一点就是,返回的数组是新生成的一个数组,

也就是说,多次运行toArray()方法会获得不同的数组对象(可以理解存储的数组对象内存地址不一样),但是这些数组对象中内容一样的。
也就是说,toArray()返回的数组是安全的,你可以对它进行任意的修改,其原因就是List不会去维持一个对该返回的数组的引用。

下面是对基本数据类型:Integer测试

public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);Object[] objects1 = list.toArray();Object[] objects2 = list.toArray();//比较二个新数组System.out.println("objects1 == objects2 : "+(objects1 == objects2));//对object1 对象的数组进行修改 不会影响到其他  引用的数组objects1[1]=4;//输出修改后的 数组System.out.println("show objects1: "+ Arrays.toString(objects1));//输出引用的数组System.out.println("show objects2: "+ Arrays.toString(objects2));//输出原来的数组System.out.println("show list: "+list);
}输出结果:objects1 == objects2 : false
show objects1: [1, 4]
show objects2: [1, 2]
show list: [1, 2]

可以看出确实toArray()返回的是一个新的数组对象地址,并且多次执行toArray()方法获得的是不同的数组对象,并且对其中一个数组进行修改,不会影响到其他toArray()方法获得的数组,并且也不会影响到list本身原来存储的元素值。


当我们list 换为其他类型对象的时候,也不影响

private static class People{String name;public People(String name){this.name = name;}@Overridepublic String toString() {return "People{" +"name='" + name + '\'' +'}';}
}public static void main(String[] args) {List<People> list = new ArrayList<>();list.add(new People("小明"));list.add(new People("小王"));Object[] objects1 = list.toArray();Object[] objects2 = list.toArray();System.out.println("objects1 == objects2 : "+(objects1 == objects2));objects1[1]=new People("小花");System.out.println("show objects1: "+ Arrays.toString(objects1));System.out.println("show objects2: "+ Arrays.toString(objects2));System.out.println("show list: "+list);输出结果:objects1 == objects2 : false
show objects1: [People{name=‘小明’}, People{name=‘小花’}]
show objects2: [People{name=‘小明’}, People{name=‘小王’}]
show list: [People{name=‘小明’}, People{name=‘小王’}]}

可以看到依然是和上面的分析结果一样,toArray()返回的是一个新的数组对象,对于toArray()返回的一个数组元素进行修改,不会影响到其他toArray()返回的数组对象,也不会影响list本身。


上面我们是对元素的自定义对象 Object1 进行修改的 ,下面我们对 元素对象本身进行 修改,?

//People类和上一个例子中的一样,这里不再列出了。
public static void main(String[] args) {List<People> list = new ArrayList<>();list.add(new People("小明"));list.add(new People("小王"));Object[] objects1 = list.toArray();Object[] objects2 = list.toArray();System.out.println("objects1 == objects2 : "+(objects1 == objects2));((People)objects1[1]).name = "小花";System.out.println("show objects1: "+ Arrays.toString(objects1));System.out.println("show objects2: "+ Arrays.toString(objects2));System.out.println("show list: "+list);
}输出结果:objects1 == objects2 : false
show objects1: [People{name=‘小明’}, People{name=‘小花’}]
show objects2: [People{name=‘小明’}, People{name=‘小花’}]
show list: [People{name=‘小明’}, People{name=‘小花’}]

对元素对象本身就行修改,会导致toArray()返回的所有数组中的内容都发生改变,包括原始的list容器里面的元素类容。从这个例子可以得出,如果list.toArray()返回的数组中存放的是list原始对象的引用,只是创建了一个新的数组来装这些引用,并没有对list中原始对象进行拷贝或复制。


toArray底层

我们可以发现 在ArrayList中的实现是调用了Arrays工具类的copyOf()方法,这个方法的作用就是 拷贝数组.


该方法是根据集合中元素的类型,传入一个相同类型的零长度的数组。返回一个指定类型的数组。
因为方法的需要,方法就是这么定义的
T[] toArray(T[] a) 参数传入一个数组,输出和参数同类型的数组,该参数相当于告诉方法要转为什么类型,所以一般传入个0长度的数组就可以了,即代码中的new String[]{}或new String[0]

toArray(T[] a)底层

总结:

  1. List接口的toArray()方法就是直接调用Arrays.copyOf(elementData,
    size),将list中的元素对象的引用装在一个新的生成数组中。
  2. List接口的toArray(T[] a)方法会返回指定类型(必须为list元素类型的父类或本身)的数组对象,如果a.length小于list元素个数就直接调用Arrays的copyOf()方法进行拷贝并且返回新数组对象,新数组中也是装的list元素对象的引用,否则先调用System.arraycopy()将list元素对象的引用装在a数组中,如果a数组还有剩余的空间,则在a[size]放置一个null,size就是list中元素的个数,这个null值可以使得toArray(T[] a)方法调用者可以判断null后面已经没有list元素了。

结合查看的 地址

第二篇:

1.ArrayList的toArray
ArrayList提供了一个将List转为数组的一个非常方便的方法toArray。toArray有两个重载的方法:

(1)list.toArray();

(2)list.toArray(T[] a);

第一种方法,是将list直接转为Object[] 数组;

第二种方法是将list转化为你所需要类型的数组,当然我们用的时候会转化为与list内容相同的类型。

大多数人会这样写:

 ArrayList<String> list=new ArrayList<String>();
for (int i = 0; i < 10; i++) {list.add(""+i);
}String[] array= (String[]) list.toArray();

结果一运行,报错:Exception in thread “main” java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

原因一看就知道了,不能将Object[] 转化为String[],转化的话只能是取出每一个元素再转化。java中的强制类型转换只是针对单个对象的,想要偷懒将整个数组转换成另外一种类型的数组是不行的,这和数组初始化时需要一个个来也是类似的。

像这样:

Object[] arr = list.toArray();
for (int i = 0; i < arr.length; i++) {String e = (String) arr[i];System.out.println(e);
}

所以第一个重构方法就不是那么好使了。

实际上,将list转化为array的时候,第二种重构方法更方便,用法如下:

String[] array =new String[list.size()];
list.toArray(array);
//实际项目中
List<String> sList = new ArrayList<String>();
for (MergeSoft mergeSoft : list) {if(mergeSoft.getCollectSoft() != null){sList.add(mergeSoft.getCollectSoft().getSid());}
}
String[] sids = sList.toArray(new String[sList.size()]);
String[] devOnlyIds = collectSoftDao.queryDevOnlyIdBySid(sids);

2:利用set 去重,和set转array

public String[] queryDevOnlyIdBySid(String[] sid) {String paramsStr = ArrayUtils.joinStringForSql(sid, "'", ",");//数组数据转为:'B07D26B8A919082612F9EFA55A9AACFC','3EF11C53F437A33A47C0B363B8D661BC'String sql = "SELECT di.devOnlyId FROM cems_device_installsoft di WHERE sId IN ( "+paramsStr+" )";List<Object> object = getSession().createSQLQuery(sql).list();Set<String> set = new HashSet<String>();for (int i = 0; i < object.size(); i++) {set.add(object.get(i).toString());//object里有重复的数据,采用set去除重复的数据}String[] devOnlyIds = new String[set.size()];    //Set-->数组    set.toArray(devOnlyIds); return devOnlyIds;
}

总结:
3.总结
1、集合转数组用方法,比如:list.toArray(new String[list.size()]);

2、利用set去除list里面重复的数据

Set<String> set = new HashSet<String>();
for(int i=0; i < object.size(); i++){set.add(object.get(i).toString());
}

然后set转为数组:

set.toArray(new String[set.size()]);

学习地址

[Java 基础] 深入理解List的toArray()方法和toArray(T[] a)方法相关推荐

  1. 深入理解List的toArray()方法和toArray(T[] a)方法

    深入理解List的toArray()方法和toArray(T[] a)方法 这两个方法都是将列表List中的元素转导出为数组,不同的是,toArray()方法导出的是Object类型数组,而toArr ...

  2. 详解List的toArray()方法和toArray(T[] a)方法

    这两个方法都是将列表List中的元素转导出为数组,不同的是,toArray()方法导出的是Object类型数组,而toArray[T[] a]方法导出的是指定类型的数组. 下面是两个方法的申明及说明, ...

  3. List的toArray()方法和toArray(T[] a)方法

    1.toArray()方法 会返回List中所有元素构成的数组,并且数组类型是Object[].还要注意一点就是,返回的数组是新生成的一个数组, 也就是说,多次运行toArray()方法会获得不同的数 ...

  4. jqgrid和ajax的区别,理解jqGrid的添加方法和Ajax请求

    我有一个现有的项目,我需要维护,但是这是我第一次满足的jqGrid ...理解jqGrid的添加方法和Ajax请求 主要是,我有一个Product,即可以有多个Formule小号.每个Formule可 ...

  5. Node.js的环境搭建方法和 npm 的使用方法

    Node.js的环境搭建方法和 npm 的使用方法 Node.js 环境的搭建 Node.js 介绍 Node.js 下载 配置Node.js node.js 测试 npm(包管理器)使用方法 npm ...

  6. 联想集群超算LICO初次使用踩坑说明(遇到的错误,一些使用方法和singularity新建容器方法)

    联想集群超算LICO初次使用踩坑说明(遇到的错误,一些使用方法和singularity新建容器方法) 说明 本文主要写一些我这几天初次使用LICO的过程中遇到的一点问题和解决的办法,还有一些模块的规范 ...

  7. JavaSE学习之路:Idea小技巧一键生成标准JavaBean(一键生成构造方法和Setter和Getter方法)

    Idea小技巧一键生成标准JavaBean(一键生成构造方法和Setter和Getter方法) 方法1:快捷键 快捷键:alt+insert或alt+fn+insert 1.生成有参和无参构造函数 p ...

  8. CString的Trim()方法和TrimStrat()和TrimEnd()方法,TrimRight()和TrimLeft() 方法

    一. CString的Trim()方法和TrimStrat()和TrimEnd()方法.这三个方法用于删除字符串头尾出现的某些字符. Trim()删除字符串头部及尾部出现的空格,删除的过程为从外到内, ...

  9. Java基础——深入理解Java中的多线程(超级详细,值得你看)

    Java中的多线程 进程(process)是程序的一次执行过程,或是正在运行的有一个程序,或是正在运行的一个程序.是一个动态的过程:有它自身的产生.存在和消亡的过程.--生命周期. 线程(thread ...

最新文章

  1. zabbix-proxy分布式监控配置
  2. 【linux基础】CMake如何生成动态链接库文件
  3. java8 多行字符串_Java8(2):Java8 对字符串连接的改进
  4. TortoiseGit上传项目到GitHub
  5. 阿里中台建设全解密:包含哪些内容?如何发挥作用?
  6. MyBatis-DynamicSQL IF判断
  7. 蒋涛:重新回归的我,将带领 CSDN 全方位升级,为 AI 转型者打造一站式平台
  8. LVS负载均衡中arp_ignore和arp_annonuce参数配置的含义
  9. 毕设题目:Matlab优化分配
  10. bin(二进制文件)
  11. 批量图片压缩、生成PDF文件及PDF文件压缩
  12. win7没有语音识别怎么办|win7系统语音识别设置方法
  13. cache abstraction
  14. 电脑变卡DOS解决方案
  15. 鼠眼看Linux调度器 by raise_sail @ chinaunix
  16. 月薪过万的运维工程师都要会干什么
  17. JAVA-多线程 三 {多线程状态}JAVA从基础开始 -- 3
  18. 【开发技术】2万字分析shiro、spring security两大安全框架,spring session,OAuth2 入门级教程
  19. ODBC连接达梦数据库
  20. 每日分享(采集网站访客流量统计程序)

热门文章

  1. Predict(生成图像)
  2. 动画和漫画里ed、op、OVA、ost、bl、gl是什么意思?
  3. 9.3.2 自然连接(NATURAL JOIN)
  4. 计算机自学知识,计算机基础知识自学
  5. 【活动】微软社区秋日巡讲——Windows Phone 应用开发训练营
  6. 3星|李笑来《财富自由之路》:标题党,励志书,提到一点投资技巧
  7. 【mysql】【binlog】mysql配置binlog
  8. 重复代码 Duplicated Code
  9. 帧缓冲区对象 FBO
  10. 计算机论文要多少截图,毕业论文可以用截图吗 毕业论文注意事项