【Java编程】之 List 与数组之间的相互转换Arrays.asList 和 ArrayList 的 subList

文章目录

  • 一、数组转换成 List 集合
  • 二、List 集合转数组
  • 浅谈 Arrays.asList
      • 1、不能往 Arrays.asList 生成的 List 集合中添加元素
      • Arrays.asList 只是简单的充当转换接口
  • 二、浅谈 ArrayList 的 subList
      • 1、subList 索引的取值边界
      • 2、subList 不可强转成 ArrayList
      • 3、对 subList 的所有操作都会映射到原列表

一、数组转换成 List 集合

1、使用 java.util 包下的 Arrays.asList 方法进行转换:

import java.util.Arrays;// 转换数组对象
Long[] arr = new Long[]{10L, 20L, 30L};
List<Long> list1 = Arrays.asList(arr);// 转换数组常量
List<String> list2 = Arrays.asList("123", "456", "789");

2、原始类型数组转包装类 List

long[] arr = new long[]{10L, 20L, 30L};
List<Long> list = Arrays.stream(arr).boxed().collect(Collectors.toList());

二、List 集合转数组

1、使用 List 集合的 toArray 方法:

// 方式1(推荐)
List<Long> list = Arrays.asList(10L, 20L, 30L);
Long[] array = list.toArray(new Long[0]);// 方式2
List<String> list = Arrays.asList("123", "456", "789");
String[] array = (String[]) list.toArray();

2、使用 Java8 流式编程方式:

// 方式1(推荐)
List<Long> list = Arrays.asList(10L, 20L, 30L);
Long[] array = list.stream().map(Long::valueOf).toArray(Long[]::new);// 方式2
List<String> list = Arrays.asList("123", "456", "789");
Long[] array = (Long[]) list.stream().map(Long::valueOf).toArray();

如果转换的数组类型为原始基本类型double[], long[], int[])的话,可以使用另一个映射方法(这几个方法已经帮我们转换成了原始基本类型):

double[] doubles = list.stream().mapToDouble(Double::new).toArray();
long[] longs = list.stream().mapToLong(Long::new).toArray();
int[] ints = list.stream().mapToInt(Integer::new).toArray();

3、使用第三方工具,比如 Apachecommons-beanutils 工具包:

<!-- 引入依赖 -->
<dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId><version>1.9.4</version>
</dependency>
import org.apache.commons.beanutils.ConvertUtils;List<String> list = Arrays.asList("123", "456", "789");
String[] array = (String[]) ConvertUtils.convert(list, String[].class);

总结:使用第三方工具包的方式通过性比较强,它可以转换任何类型,但使用 List 集合的 toArray 方法和 Java8 的流式编程比较简单方便,不需要引入其它依赖,所以比较推荐。


浅谈 Arrays.asList

1、不能往 Arrays.asList 生成的 List 集合中添加元素

1)场景

Arrays.asList() 方法很方便地为我们快捷创建一个 List 集合,比如:

List<String> list = Arrays.asList("123", "456", "789");

但是,如果我们往生成的 list 添加元素时:

list.add("2233");

会抛出 java.lang.UnsupportedOperationException 异常:

java.lang.UnsupportedOperationExceptionat java.util.AbstractList.add(AbstractList.java:148)at java.util.AbstractList.add(AbstractList.java:108)

也就是说,使用 Arrays.asList 生成的 List 集合不允许添加元素。

2)原因

要找出原因,我们需要回到源码当中,进入 atList 源码:

// atList 方法源码
public static <T> List<T> asList(T... a) {return new ArrayList<>(a);
}// Arrays 的静态内部类 ArrayList
private static class ArrayList<E> extends AbstractList<E>implements RandomAccess, java.io.Serializable
{private static final long serialVersionUID = -2764017481108945198L;private final E[] a;......
}

从源码中可以看出,Arrays.asList 返回的是 Arrays 类中的静态内部类 ArrayList对象,并非是 java.util 包下的 ArrayList 类对象。

虽然这个静态内部类 ArrayList 同样是继承了 AbstractList 类,但它只实现了 getsetcontainindexOf 等方法,却没有实现 addremoveclear 等方法来支持添加、删除操作。

3)总结

当我们使用 Arrays.asList 把数组转换成集合时,不能使用其修改集合的相关方法,一般只是适用于遍历访问操作。

Arrays.asList 只是简单的充当转换接口

Arrays.asList 体现的是适配器模式,只是转换接口,后台的数据仍然是数组,如果修改了原数组数据,其生产的 List 集合数据也会跟着一起被修改:

// 原数组数据
String[] strs = new String[]{"123", "456", "789"};// 生成 List 集合
List<String> list = Arrays.asList(strs);
System.out.println(list.toString());// 修改原数组数据
strs[0] = "666";
System.out.println(list.toString());>>>>>>
[123, 456, 789]
[666, 456, 789]

二、浅谈 ArrayList 的 subList


1、subList 索引的取值边界

下面是一个简单的 subList 示例:

List<String> list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
List<String> subList = list.subList(0, 2);
System.out.println(subList);>>>>
[111, 222]

可以看出,subList 的索引是从 fromIndex(包含)到 toIndex(不包含)。

2、subList 不可强转成 ArrayList

我们进去看一下 ArrayList 的 subList 方法源码:

// subList 方法
public List<E> subList(int fromIndex, int toIndex) {subListRangeCheck(fromIndex, toIndex, size);return new SubList(this, 0, fromIndex, toIndex);
}// ArrayList 内部类 SubList
private class SubList extends AbstractList<E> implements RandomAccess {private final AbstractList<E> parent;private final int parentOffset;private final int offset;int size;......
}

可以发现,subList 返回的是 ArrayList 的成员内部类 SubList,如果强转成 ArrayList 的话会抛出异常:java.lang.ClassCastException: java.util.ArrayList$SubList cannot be cast to java.util.ArrayList

3、对 subList 的所有操作都会映射到原列表

1)非结构性修改会相互影响

究其原因,subList 返回的内部类 SubList 是 ArrayList 的一个视图,对 SubList 子列表的所有操作最终都会映射到原列表上(对原列表的操作也会影响子列表),如下示例:

// 创建父子列表
List<String> list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
List<String> subList = list.subList(0, 2);
System.out.println(list);
System.out.println(subList);// 修改原列表
list.set(0, "666");
System.out.println(list);
System.out.println(subList);// 修改子列表
subList.set(0, "888");
System.out.println(list);
System.out.println(subList);>>>>>
[111, 222, 333]
[111, 222]
---------------
[666, 222, 333]
[666, 222]
---------------
[888, 222, 333]
[888, 222]

2)对父集合的增加或删除(结构性修改),都会导致子列表的遍历、增加、删除产生 ConcurrentModificationExcetption 异常

List<String> list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
List<String> subList = list.subList(0, 2);// 原列表添加元素
list.add("666");System.out.println(list);		// 遍历父列表
System.out.println(subList);	// 遍历子列表>>>>
[111, 222, 333, 666]
java.util.ConcurrentModificationExceptionat java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1239)at java.util.ArrayList$SubList.listIterator(ArrayList.java:1099)at java.util.AbstractList.listIterator(AbstractList.java:299)at java.util.ArrayList$SubList.iterator(ArrayList.java:1095)at java.util.AbstractCollection.toString(AbstractCollection.java:454)

从上面可以看出,对原集合进行添加操作(结构性修改),会导致遍历子集合时引起ConcurrentModificationExcetption 异常。

注意:ConcurrentModificationExcetption 异常并不是在添加元素时发生的,而是在添加元素后,遍历子集合时发生的。

3)对子列表结构性修改会影响原列表但不会触发异常

List<String> list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
List<String> subList = list.subList(0, 2);// 子列表添加元素
subList.add("666");System.out.println(list);
System.out.println(subList);>>>>>
[111, 222, 666, 333]
[111, 222, 666]

从上面可以看出,对子列表的结构性修改会影响到父列表,但遍历的时候不会引起异常。

4)总结

ArrayList 的 subList 方法,返回的是原集合的一个子集合(视图),非结构性修改任意一个集合的元素的值,都会彼此影响;结构性修改原集合时,会报 ConcurrentModificationException 异常,而结构性修改子集合时,会影响原集合,但不会报异常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/554743.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谈Java集合类的toArray()的小bug

谈Java集合类的toArray()的小bug toArray()方法 它的作用是将集合转换成数组。但是这个方法有一个弊端&#xff0c;当toArray()方法使用不当时会产生ClassCastException&#xff08;类转换异常&#xff09; public static void main(String[] args) {List<Integer> li…

Dubbo系统里面MultipartFile文件传输问题Dubbo文件上传/传输服务

今天遇到一个问题&#xff0c;在Controller 层里面&#xff0c;直接使用MultipartFile 来接收上传的图片&#xff0c;遇到几个坑。 一、在spring配置文件里面配置文件上传 <!--文件上传--><bean name"multipartResolver"class"org.springframework.web…

Dubbo2.7文档详解

本篇博文参考dubbo官方文档 本编博文参考javaguide之rpc 文章目录一.RPC1.1 什么是 RPC?1.2 为什么要用 RPC?1.3 RPC 能帮助我们做什么呢&#xff1f;1.4 RPC 的原理是什么?1.5 常见的 RPC 框架总结二.既有 HTTP ,为啥用 RPC 进行服务调用?2.1 RPC只是一种设计而已2.2 HTTP…

12nm 制程、Zen+ 微架构 AMD Ryzen 7 2700X 处理器详细测试 - 电脑领域 HKEPC Hard

12nm 制程、Zen 微架构 AMD Ryzen 7 2700X 处理器详细测试 代号 Pinnacle Ridge、AMD 第二代 Ryzen 处理器正式登场&#xff0c;基于经改良的 Zen 微架构&#xff0c;改善了 Cache 及记忆体延迟表现&#xff0c;更先进的 12nm LP 制程&#xff0c;令核心时脉进一步提升&#…

Java之Serializable接口实现序列化和反序列化实例以及部分序列化的四种方法

首先需要明确的概念: 序列化&#xff1a;将数据结构或对象转换成二进制字节流的过程反序列化&#xff1a;将在序列化过程中所生成的二进制字节流的过程转换成数据结构或者对象的过程持久化&#xff1a;将数据写入文件中长久保存的过程称之为持久化序列化主要目的&#xff1a;是…

win10死机频繁怎么解决

Windows 10已经推出好几年&#xff0c;系统趋于稳定&#xff0c;但依旧不是完美&#xff0c;蓝屏、死机状态还是会出现&#xff0c;只是概率降低了很多&#xff0c;如果你的电脑遇到了突然死机或者频繁卡死的情况&#xff0c;或许你应该考虑对电脑进行重置了。系统自带的恢复重…

Jar包常见的反编译工具介绍与使用

反编译JAR能干什么: 排查问题、分析商业软件代码逻辑&#xff0c;学习优秀的源码思路。 反编译工具介绍 JD-GUI 下载地址&#xff1a;http://java-decompiler.github.io/ 点评&#xff1a;支持的java版本不会太高&#xff0c;中文注释能够正常显示。 Luyten 下载地址&#…

400 bad request的原因意思和解决方法

我们的电脑在使用的过程中&#xff0c;有的小伙伴在上网的时候可能就遇到过系统提示&#xff1a;400 bad request的情况。据小编所知这种情况&#xff0c;大致意思就是出现了错误的请求或者请求不能满足。原因是因为我们请求的语法格式出现呢错误或者其他情况等等。我们可以通过…

final关键字的作用 (修改方法、变量、类)

文章目录前言final关键字的含义?什么是final变量&#xff1f;什么是final方法?什么是final类&#xff1f;final关键字的好处关于final的重要知识点前言 Java中的final关键字非常重要&#xff0c;它可以应用于类、方法以及变量。这篇文章中我将带你看看什么是final关键字&…

重装系统win10提示磁盘布局不受UEFI固件支持怎么办

原因分析&#xff1a; Win10系统新增UEFI检测机制&#xff0c;在BIOS开启了UEFI时&#xff0c;如果硬盘分区表格式不是GPT&#xff0c;则会提示无法重装系统win10&#xff0c;也就是说UEFIGPT或LegacyMBR才能安装win10。 解决方法一&#xff1a;关闭UEFI 1、重启系统时按Del…

win7按f8后没有进入安全模式怎么解决

win7f8后没有进入安全模式&#xff0c;在正确操作按F8没有进入安全模式之后&#xff0c;不知道怎么解决win7按f8后没有进入安全模式怎么解决&#xff0c;其实非常的简单&#xff0c;下面来看看详细的解决方法吧。 win7按f8后没有进入安全模式怎么解决 第一种方法&#xff1a;…

使用toArray将List转数组:使用Call to ‘toArray()‘ with pre-sized array argument ‘new String[list.size()]‘

代码示例&#xff1a; public static void main(String[] args) {List<String> list new ArrayList<String>();list.add("java");list.add("flink");list.add("spring");//第一种写法&#xff1a;该写法不规范String[] array1 li…

电脑开机就进入bios的解决方法

最近很多人反映自己的电脑一开机就直接进入bios里&#xff0c;无法正常进入系统。这是怎么回事呢?开机进入bios无法进入系统怎么办呢?别着急&#xff0c;今天就为大家带来电脑开机就进入bios的解决方法。 电脑开机就进入bios的解决方法&#xff1a; 1、如果是电脑的硬盘出了…

Serializable序列化和Externalizable序列化与反序列化的使用

1、序列化是干啥用的&#xff1f; 序列化的原本意图是希望对一个Java对象作一下“变换”&#xff0c;变成字节序列&#xff0c;这样一来方便持久化存储到磁盘&#xff0c;避免程序运行结束后对象就从内存里消失&#xff0c;另外变换成字节序列也更便于网络运输和传播&#xff…

Win10系统如何查看电脑是否是UEFI启动模式

Win10系统如何查看电脑是否是UEFI启动模式?现在越来越多的新电脑都采用UEFI来引导电脑系统&#xff0c;UEFI提高了开机后操作系统的启动速度&#xff0c;使电脑更加流畅&#xff0c;安全性更强&#xff0c;而传统的BIOS则没有UEFI用起来那么好。如何查看自己Win10系统电脑是否…

win10如何关闭Windows Defender安全保护程序

win10如何关闭Windows Defender安全保护程序&#xff1f;win10如何关闭Windows Defender安全保护程序?在安装的windows操作系统中&#xff0c;自带着安全保护程序“Windows Defender应用”&#xff0c;其实主要是为了保护好其他运行的软件&#xff0c;那该怎么来关闭这个软件呢…

7种抓包工具详细介绍

在处理IP网络的故障时&#xff0c;经常使用以太网抓包工具来查看和抓取IP网络上某些端口或某些网段的数据包&#xff0c;并对这些数据包进行分析&#xff0c;定位问题。 在 IMON项目里&#xff0c;使用抓包工具抓包进行分析的场景在EPG采集、引流模块和软终端监看模块&#xf…

2020-12-11

bios怎么恢复出厂设置? 1 第一步 打开电脑 在电脑出现开机提示时按下热键(一般是del或F2)就可以进入到bios设置界面 2 第二步 在bios设置界面中找到并选择“Load Optimized Default”&#xff0c; 然后按下回车键 3 第三步 在弹出窗口中选择“OK“ 然后回车键确定即可 …

JAVA序列化和反序列化的底层实现原理解析 更新时间:2019年11月27日 14:38:39 作者:myseries 这篇文章主要介绍了JAVA序列化和反序列化的底层实现原理解析,文中通

一、基本概念 1、什么是序列化和反序列化 &#xff08;1&#xff09;Java序列化是指把Java对象转换为字节序列的过程&#xff0c;而Java反序列化是指把字节序列恢复为Java对象的过程&#xff1b; &#xff08;2&#xff09;序列化&#xff1a;对象序列化的最主要的用处就是在…

笔记本电脑重启快捷键是什么

品牌型号&#xff1a;联想小新Air-14 2020 系统&#xff1a;win10 1909 64位企业版 部分用户可能电脑型号不一样&#xff0c;但系统版本一致都适合该方法。 用电脑用久了的朋友们都知道电脑的快捷键在哪里&#xff0c;笔记本电脑重启快捷键是什么?下面就给大家分享一下笔记…