文章目录

  • 集合、数组互转
    • 集合 --> 数组
      • 1. 循环添加
      • 2. toArray
    • 数组 --> 集合
      • 1. 循环添加
      • 2. asList()
    • 集合 <--> 集合
      • 1. 构造方法
      • 2. addAll() 方法
  • 数组的拷贝
    • 1. for
    • 2. clone()
    • 3. System.arraycopy()
    • 4. Arrays.copyOf()
      • tips
  • 基本数据类型

集合、数组互转

集合 --> 数组

1. 循环添加

 List<String> mlist = new ArrayList();mlist.add("A");mlist.add("L");mlist.add("V");String[] arr = new String[mlist.size()];// List转换成数组for (int i = 0; i < mlist.size(); i++) {arr[i] = mlist.get(i);}

2. toArray

Conllection, List, Set接口中都具有toArray()toArray(T[] a)方法。

所以实现这些接口的类都可以使用toArray方法转换为数组。

ArrayList 中的源码

 // ArrayList 中的源码public Object[] toArray() {return Arrays.copyOf(elementData, size);}public <T> T[] toArray(T[] a) {if (a.length < size)// Make a new array of a's runtime type, but my contents:return (T[]) Arrays.copyOf(elementData, size, a.getClass());System.arraycopy(elementData, 0, a, 0, size);if (a.length > size)a[size] = null;return a;}
 /** @param      src      the source array.源数组* @param      srcPos   starting position in the source array.源数组要复制的起始位置* @param      dest     the destination array.目的数组* @param      destPos  starting position in the destination data.目的数组放置的起始位置* @param      length   the number of array elements to be copied.复制的长度**/public static native void arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);

使用示例:

    List<String>  sList = new ArrayList<>();sList.add("A");sList.add("B");sList.add("C");Object[] objArr = sList.toArray();// String[] errArr  = (String[] )sList.toArray(); // 报错// Exception in thread "main" java.lang.ClassCastException:// [Ljava.lang.Object; cannot be cast to [Ljava.lang.String; at com.company.Main.main(Main.java:136)String[] strArr = sList.toArray(new String[sList.size()]); // 常用此方法

String[] errArr = (String[] )sList.toArray(); // 报错原因
因为java中的强制类型转换是针对单个对象才有效果的,而List是多对象的集合,所以强制转换整个List是错误的。

数组 --> 集合

1. 循环添加

    String[] strs = new String[]{"A", "L", "V", "I", "N"};List<String> newList = new ArrayList<String>();for(String str : strs)newList.add(str);System.out.println(newList); // [A, L, V, I, N]System.out.println(newList.toString()); // [A, L, V, I, N]System.out.println(Arrays.toString(newList.toArray())); // [A, L, V, I, N]

2. asList()

Arrays中有方法asList();

    public static <T> List<T> asList(T... a) {return new ArrayList<>(a); // 这儿的ArrayList是Arrays类的内部类,其中没有add(),remove()之类的方法;只能查改、不能增删}private static class ArrayList<E> extends AbstractList<E>implements RandomAccess, java.io.Serializable {...}

这儿的ArrayList是Arrays类的内部类,其中没有add(),remove()之类的方法;只能查改、不能增删

使用示例

    String[] strs = new String[]{"A", "L", "V", "I", "N"};List<String> list = Arrays.asList(strs);// list.add("can't add or del!!!");// Exception in thread "main" java.lang.UnsupportedOperationExceptionList<String> newList = new ArrayList<String>(list);newList.add("can add or del!!!"); // 利用ArrayList构造方法,将其变为可变集合for (String bean : newList) {System.out.println(bean);}

List<String> list = Arrays.asList(strs);
list.add("can't add or del!!!");
Exception in thread “main” java.lang.UnsupportedOperationException

集合 <–> 集合

1. 构造方法

// 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。
ArrayList(Collection<? extends E> c)LinkedList(Collection<? extends E> c)// 构造一个包含指定集合中的元素的新集合。
HashSet(Collection<? extends E> c)// 构造与指定集合相同的元素的新的链接散列集。
LinkedHashSet(Collection<? extends E> c)// 构造一个包含指定集合元素的deque,按照它们由集合的迭代器返回的顺序。
ArrayDeque(Collection<? extends E> c)
// 创建与指定的枚举映射相同的键类型的枚举映射,最初包含相同的映射(如果有)。
EnumMap(EnumMap<K,? extends V> m)// 构造一个与给定地图相同的映射的新哈希表。
Hashtable(Map<? extends K,? extends V> t)// 构造一个新的 HashMap与指定的相同的映射 Map 。
HashMap(Map<? extends K,? extends V> m)

做个测试:判断是浅复制 还是 深复制!

package com.company;import java.util.ArrayList;
import java.util.List;public class ClassLoaderTest {public static void main(String[] args){ArrayList<Integer> list = new ArrayList();for(int i = 0;i<5;i++)list.add(i);ArrayList<Integer> copy = new ArrayList(list);System.out.println(list); // [0, 1, 2, 3, 4]System.out.println(copy); // [0, 1, 2, 3, 4]System.out.println(list.get(0) == copy.get(0)); // trueSystem.out.println(list.get(0).equals(copy.get(0))); // true// ---------------------------------------------------ArrayList<String> list2 = new ArrayList();for(int i = 6;i<10;i++)list2.add(String.valueOf(i));ArrayList<String> copy2 = new ArrayList(list2);System.out.println(list2); // [6, 7, 8, 9]System.out.println(copy2); // [6, 7, 8, 9]System.out.println(list2.get(0) == copy2.get(0)); // trueSystem.out.println(list2.get(0).equals(copy2.get(0))); // true// --------------------------------------------------------ArrayList<TreeNode> list3 = new ArrayList();for(int i = 10;i<15;i++)list3.add(new TreeNode(i));ArrayList<TreeNode> copy3 = new ArrayList(list3);System.out.println(list3); // [10, 11, 12, 13, 14]System.out.println(copy3); // [10, 11, 12, 13, 14]copy3.get(0).val = 1000; System.out.println(list3.get(0) == copy3.get(0)); // trueSystem.out.println(list3.get(0).equals(copy3.get(0))); // trueSystem.out.println(list3); // [1000, 11, 12, 13, 14]System.out.println(copy3); // [1000, 11, 12, 13, 14]}
}class TreeNode {int val;TreeNode(int val) { this.val = val; }public String toString(){return String.valueOf(val);}
}

对于引用类型,构造方式是直接复制地址!!!

Integer、String具有特殊性

Java拷贝(赋值、浅拷贝、深拷贝)

2. addAll() 方法

实现了List接口的类具有该方法:ArrayList、LinkedList

    public boolean addAll(Collection<? extends E> c) {Object[] a = c.toArray();int numNew = a.length;ensureCapacityInternal(size + numNew);  // Increments modCountSystem.arraycopy(a, 0, elementData, size, numNew);size += numNew;return numNew != 0;}

数组的拷贝

  1. for循环
  2. clone()
  3. System.arraycopy()
  4. Arrays.copyOf()

1. for

for循环是一种很灵巧的数组拷贝方式,经常可以自己封装成方法去使用。

记不住其他的方式时候,自己手敲,最方便了。

2. clone()

protected native Object clone() throws CloneNotSupportedException;

这是数组的clone()方法。

      User u1 = new User(1,"1",null);User u2 = new User(2,"2",u1);User u3 = new User(3,"3",u2);User[] users = new User[3];users[0] = u1; users[1] = u2; users[2] = u3;User[] users_c = users.clone();users_c[0].id = 9;users_c[0].name = "change";users_c[0].friend = users_c[2];System.out.println(users_c == users);      // falseSystem.out.println(users_c[0] == users[0]);   // trueSystem.out.println(users[0].toString());         // [9-change-3]System.out.println(users_c[0].toString());   // [9-change-3]

发现对于引用类型的数组 复制的是数组元素的地址

3. System.arraycopy()

 /** @param      src      the source array.源数组* @param      srcPos   starting position in the source array.源数组要复制的起始位置* @param      dest     the destination array.目的数组* @param      destPos  starting position in the destination data.目的数组放置的起始位置* @param      length   the number of array elements to be copied.复制的长度**/public static native void arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);

native修饰,底层用c或者c++实现的,但没有返回值,clone()还需要对返回值进行类型转换,它的速度是要比clone()要快。
四种拷贝中最快的肯定是System.arraycopy()。

4. Arrays.copyOf()

Arrays.copyOf(original, newLength);
Arrays.copyOfRange(original, from, to);

两者本质上还是调用的System.arraycopy(...)方法

源码

基本数据类型

 // 基本数据类型都是调用的 System.arraycopy(...)方法public static int[] copyOf(int[] original, int newLength) {int[] copy = new int[newLength];System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;}public static int[] copyOfRange(int[] original, int from, int to) {int newLength = to - from;if (newLength < 0)throw new IllegalArgumentException(from + " > " + to);int[] copy = new int[newLength];System.arraycopy(original, from, copy, 0,Math.min(original.length - from, newLength));return copy;}

引用数据类型

    public static <T> T[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass());}public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {@SuppressWarnings("unchecked")T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;}public static <T> T[] copyOfRange(T[] original, int from, int to) {return copyOfRange(original, from, to, (Class<? extends T[]>) original.getClass());}public static <T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {int newLength = to - from;if (newLength < 0)throw new IllegalArgumentException(from + " > " + to);@SuppressWarnings("unchecked")T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);System.arraycopy(original, from, copy, 0,Math.min(original.length - from, newLength));return copy;}

两者本质上还是调用的System.arraycopy(...)方法

使用

// 基本数据类型使用 B 代替
// 复制指定的数组,用空值截断或填充(如有必要),以便复制具有指定的长度。
static B[] copyOf(B[] original, int newLength)
// 将指定数组的指定范围复制到新数组中。
static B[]  copyOfRange(B[] original, int from, int to)// 对象
// 复制指定的数组,用空值截断或填充(如有必要),以便复制具有指定的长度。
static <T> T[]    copyOf(T[] original, int newLength)// 将指定数组的指定范围复制到新数组中。
static <T> T[]    copyOfRange(T[] original, int from, int to)

tips

基本数据类型都是直接复制值!

那么引用类型呢?见下:

除了String,一般引用数据类型都是直接复制数组元素地址。
浅拷贝是针对单个对象来说的。而这儿讨论的是数组的复制。

String

     String[] strs = new String[]{"A", "L", "V", "I", "N"};List<String> newList = new ArrayList<String>();String[] strs_c = Arrays.copyOf(strs, strs.length);strs_c[0] ="exchange";System.out.println(Arrays.toString(strs)); // [A, L, V, I, N]System.out.println(Arrays.toString(strs_c)); // [exchange, L, V, I, N]System.out.println(strs == strs_c);             // falseSystem.out.println(strs[0] == strs_c[0]);       // falseSystem.out.println(strs[0].equals(strs_c[0]));  // false

System.arraycopy(...)Arrays.copyOf(...) : 重新创建String对象

自定义数据类型

class User{int id;String name;User friend;public User(int id,String name,User friend){this.friend =friend;this.id = id;this.name = name;}public String toString(){return "["+this.id + "-"+ this.name +"-"+ this.friend.id + "]";}
}class Main{public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {User u1 = new User(1,"1",null);User u2 = new User(2,"2",u1);User u3 = new User(3,"3",u2);User[] users = new User[3];users[0] = u1; users[1] = u2; users[2] = u3;User[] users_c = Arrays.copyOf(users,3);users_c[0].id = 9;users_c[0].name = "change";users_c[0].friend = users_c[2];System.out.println(users_c == users);      // falseSystem.out.println(users_c[0] == users[0]); // trueSystem.out.println(users[0].toString());   // [9-change-3]System.out.println(users_c[0].toString());   // [9-change-3]}
}
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {User u1 = new User(1,"1",null);User u2 = new User(2,"2",u1);User u3 = new User(3,"3",u2);User[] users = new User[3];users[0] = u1; users[1] = u2; users[2] = u3;User[] users_c = users.clone();   //使用数组的clone()方法也一样users_c[0].id = 9;users_c[0].name = "change";users_c[0].friend = users_c[2];System.out.println(users_c == users);      // falseSystem.out.println(users_c[0] == users[0]); // trueSystem.out.println(users[0].toString());   // [9-change-3]System.out.println(users_c[0].toString());   // [9-change-3]}

System.arraycopy(...)Arrays.copyOf(...) 还有 数组[].clone() : 都是复制每个对象的地址,等同于 users_c[0] = users[0];


java数组的四种拷贝方式
Java拷贝(赋值、浅拷贝、深拷贝)

基本数据类型

待增加

Java数组的转换和拷贝相关推荐

  1. java 数组集合转换_Java 实例 – 集合转数组

    Java 实例 - 集合转数组 以下实例演示了如何使用 Java Util 类的 list.add() 和 list.toArray() 方法将集合转为数组: /* author by w3cscho ...

  2. java 数组的方法_数组常用方法

    [TOC] # 定义 ~~~ //初始化一个长度为8的定长数组,其所有元素均为0 val arr1 = new Array[Int](8) //直接打印定长数组,内容为数组的hashcode值 pri ...

  3. java 数组的拷贝 对象数组的拷贝 System.arraycopy函数

    /* java 数组的操作   System类的arraycopy静态函数用于数组拷贝   数组是不能越界的 对象数组的复制实际上是复制的引用的拷贝  也就是对象的地址  */ class Point ...

  4. 【Java】总结Java数组的拷贝和输出

    Java的clone()方法 想clone(),先需要实现Cloneable接口,如此才能拷贝. 众所周知,Java中的clone()多为浅拷贝,即只复制引用,不会另外开辟完整空间重新存储的,一旦原先 ...

  5. Java中List与数组互相转换

    1.说明 在Java中,经常遇到需要List与数组互相转换的场景. List转换成数组,可以使用List的toArray()或者toArray(T[] a)方法. 数组转换成List,可以使用Arra ...

  6. Java学习之路:第七天(三)数组的遍历与拷贝

    数组的遍历: 利用for循环和for-each语句. 数组拷贝利用System.arraycopy()进行 测试代码如下: /*** 数组的遍历与拷贝*/ package Array;import j ...

  7. Java字符串中分隔符的字符串和数组的转换

    在做批量删除数据的时候,前端传来的是以逗号分隔的字符串,要拿到service层进行处理分割,还原成数组或者ArrayList集合,经过网上查阅,总结如下,话不多说直接上代码 第一种方式(split) ...

  8. Java数组赋值数组复制(拷贝)

    Java数组赋值&数组复制(拷贝) 数组赋值 数组复制 1⃣️数组赋值 值传递(基本数据类型)与引用传递(数组)区别 值传递:基本数据类型赋值,赋给变量的值就是具体的数据,而且相互不受影响: ...

  9. Java数组与容器类分析资料--数组、List和Set、Map等

    2019独角兽企业重金招聘Python工程师标准>>> Java容器分析--数组 数组是Java语言内置的类型,除此之外,Java有多种保存对象引用的方式.Java类库提供了一套相当 ...

最新文章

  1. python画图小房子代码-python少儿编程-turtle 基本绘图
  2. 数据库集群技术 -摘自网络
  3. linux python连接oracle数据库_Linux下通过python访问MySQL、Oracle、SQL Server数据库的方法...
  4. JavaScript中正则表达式学习笔记
  5. va_list/va_start/va_end的使用
  6. js中while死循环语句_JavaScript循环 - while
  7. 微信表情图像代表什么意思_微信的表情都是什么意思(微信表情含义图解大全)...
  8. 计算机声音如何处理器,我电脑运行的声音很大,而且CPU的温度总在70到80之间,怎么办啊?...
  9. Web网页——留言板功能
  10. Scala中fold()操作和reduce()操作的区别
  11. 【JavaScript】JS高级-面向对象编程
  12. 单变量微积分笔记1——导数1(导数的基本概念)
  13. pad看linux源码,在 iPad和 iPhone的浏览器上查看网页源代码
  14. MT6735 刷机时:brom error:s ft download fail 4008
  15. 远端WWW服务支持TRACE请求
  16. WinForm DevExpress使用-(ChartControl控件绘制图表)
  17. html代码编辑器jason,GitHub - 2947721120/jsoneditor: json编辑器
  18. 基于采样的路径规划算法总结:RRT-Matlab实现
  19. 如何使用CAM350打开gerber文件
  20. Apollo学习笔记(7)车辆运动学模型

热门文章

  1. mysql 复制功能_从MySQL复制功能中得到的一举三得实惠分析
  2. git 小乌龟 配置_Git-Bash和TortoiseGit小乌龟客户端配置记录
  3. 简述linux内核中,Linux内核中的文件描述符(一)——基础知识简介
  4. cookie分号后面没有值_浏览器Cookie介绍
  5. PCB Genesis脚本 C#调用Javascript
  6. Maven 中央仓库及阿里云仓库地址
  7. javascript 键值keyCode
  8. Log4J 1.x 配置详解
  9. SystemTimer,TimerTaskList等源码分析
  10. (90)FPGA面试题-使用Verilog实现可预置初值的7进制循环计数器