Java集合(Iterator、Collection、List、Set、Map)

内容来源:Java集合、泛型和枚举

1. 集合简介

       在 Java 中数组的长度是不可修改的。然而在实际应用的很多情况下,无法确定数据数量。这些数据不适合使用数组来保存,这时候就需要使用集合。

       Java 的集合就像一个容器,用来存储 Java 类的对象。有些容器内部存放的东西在容器内部是不可操作的,像水瓶里的水,除了将其装入和倒出之外,就不能再进行别的操作了,但是很容易装入和倒出;而有些容器内部存放的东西在容器内部是可以操作的,例如,衣柜里面摆放的衣服,不仅可以将衣服存放到衣柜中,还可以将衣服有序地摆放,以便在使用时快速查找,但是却不容易取出。Java 的集合类比这些容器功能还多,其中有些是方便放入和取出的,有些是方便查找的。在集合中经常会用到泛型来使集合更加安全。

       在编程时,可以使用数组来保存多个对象,但数组长度不可变化,一旦在初始化数组时指定了数组长度,这个数组长度就是不可变的。如果需要保存数量变化的数据,数组就有点无能为力了。而且数组无法保存具有映射关系的数据,如成绩表为语文----79,数学——80,这种数据看上去像两个数组,但这两个数组的元素之间有一定的关联关系。

       为了保存数量不确定的数据,以及保存具有映射关系的数据(也被称为关联数组),Java 提供了集合类。集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。Java 所有的集合类都位于 java.util 包下,提供了一个表示和操作对象集合的统一构架,包含大量集合接口,以及这些接口的实现类和操作它们的算法。

       集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的引用变量),而集合里只能保存对象(实际上只是保存对象的引用变量,但通常习惯上认为集合里保存的是对象)。

       Java 集合类型分为 Collection 和 Map,它们是 Java 集合的根接口,这两个接口又包含了一些子接口或实现类。图 1 和图 2 分别为 Collection 和 Map 的子接口及其实现类。

图 1 Collection接口基本结构

图 2 Map接口基本结构

在 图 1 和图 2 中,黄色块为集合的接口,蓝色块为集合的实现类。表 1 介绍了这些接口的作用。

       对于 Set、List、Queue 和 Map 这 4 种集合,Java 最常用的实现类分别是 HashSet、TreeSet、ArrayList、ArrayDueue、LinkedList 和 HashMap、TreeMap 等。表 2 介绍了集合中这些常用的实现类。

2. Collection接口详解

       Collection 接口是 List、Set 和 Queue 接口的父接口,通常情况下不被直接使用。Collection 接口定义了一些通用的方法,通过这些方法可以实现对集合的基本操作。定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。

注意:

  • 由于Collection是接口,不能对其实例化,所以以上方法都是对集合接口的实现类(List接口的实现类ArrayList)所创建的对象进行实现的,例如:list.add()、list.addAll(list2)、list.iterator()(此方法得到的结果是一个迭代器,可通过while(iterator.hasNext())、iterator.next()对集合元素进行遍历)等。

  • retainAll( ) 方法的作用与 removeAll( ) 方法相反,即保留两个集合中相同的元素,其他全部删除。

  • 集合元素下标索引从0开始。

  • 集合的元素类型一般要加泛型进行约束。

2.1 遍历集合元素

2.1.1 使用Lambda表达式遍历Collection集合

       Java 8 为 Iterable 接口新增了一个 forEach(Consumer action) 默认方法,该方法所需参数的类型是一个函数式接口,而 Iterable 接口是 Collection 接口的父接口,因此 Collection 集合也可直接调用该方法。

       当程序调用 Iterable 的 forEach(Consumer action) 遍历集合元素时,程序会依次将集合元素传给 Consumer 的 accept(T t) 方法(该接口中唯一的抽象方法)。正因为 Consumer 是函数式接口,因此可以使用 Lambda 表达式来遍历集合元素。例如:

 lists.foreach(list->System.out.println(e))
 或
 lists.foreach(System.out::println)。

2.1.2 使用Iterator(迭代器)遍历Collection集合元素

       Iterator(迭代器)是一个接口,它的作用就是遍历容器的所有元素,也是 Java 集合框架的成员,但它与 Collection 和 Map 系列的集合不一样,Collection 和 Map 系列集合主要用于盛装其他对象,而 Iterator 则主要用于遍历(即迭代访问)Collection 集合中的元素。

       Iterator 接口隐藏了各种 Collection 实现类的底层细节,向应用程序提供了遍历 Collection 集合元素的统一编程接口。

Iterator 接口里定义了如下 4 个方法。

  • boolean hasNext():如果被迭代的集合元素还没有被遍历完,则返回 true。

  • Object next():返回集合里的下一个元素。

  • void remove():删除集合里上一次 next 方法返回的元素。

  • void forEachRemaining(Consumer action):这是 Java 8 为 Iterator 新增的默认方法,该方法可使用 Lambda 表达式来遍历集合元素。

注意:

       (a)Iterator 必须依附于 Collection 对象,若有一个 Iterator 对象,则必然有一个与之关联的 Collection 对象。Iterator 提供了两个方法来迭代访问 Collection 集合里的元素,并可通过 remove() 方法来删除集合中上一次 next() 方法返回的集合元素。

       (b)当使用 Iterator 对集合元素进行迭代时,Iterator 并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代变量的值对集合元素本身没有任何影响。

       (c)当使用 Iterator 迭代访问 Collection 集合元素时,Collection 集合里的元素不能被改变,只有通过 Iterator 的 remove() 方法删除上一次 next() 方法返回的集合元素才可以,否则将会引发“java.util.ConcurrentModificationException”异常。

       (d)Iterator 迭代器采用的是快速失败(fail-fast)机制,一旦在迭代过程中检测到该集合已经被修改(通常是程序中的其他线程修改),程序立即引发 ConcurrentModificationException 异常,而不是显示修改后的结果,这样可以避免共享资源而引发的潜在问题。快速失败(fail-fast)机制,是 Java Collection 集合中的一种错误检测机制。

       注意:上面程序如果改为删除“C语言中文网C语言教程”字符串,则不会引发异常。对于 HashSet 以及后面的 ArrayList 等,迭代时删除元素都会导致异常。只有在删除集合中的某个特定元素时才不会抛出异常,这是由集合类的实现代码决定的,程序员不应该这么做。

2.1.3 使用Lambda表达式遍历Iterator迭代器

       Java 8 为 Iterator 引入了一个 forEachRemaining(Consumer action) 默认方法,该方法所需的 Consumer 参数同样也是函数式接口。当程序调用 Iterator 的 forEachRemaining(Consumer action) 遍历集合元素时,程序会依次将集合元素传给 Consumer 的 accept(T t) 方法(该接口中唯一的抽象方法)。

       java.util.function 中的 Function、Supplier、Consumer、Predicate 和其他函数式接口被广泛用在支持 Lambda 表达式的 API 中。“void accept(T t);”是 Consumer 的核心方法,用来对给定的参数 T 执行定义操作。例如:

 // 获取objs集合对应的迭代器
 Iterator it = objs.iterator();
 // 使用Lambda表达式(目标类型是Comsumer)来遍历集合元素
 it.forEachRemaining(obj -> System.out.println("迭代集合元素:" + obj));

2.1.4 foreach遍历Collection集合

       还可以使用 Java 5 提供的 foreach 循环迭代访问集合元素,而且更加便捷。使用 foreach 循环来迭代访问 Collection 集合里的元素更加简洁,这正是 JDK 1.5 的 foreach 循环带来的优势。与使用 Iterator 接口迭代访问集合元素类似的是,foreach 循环中的迭代变量也不是集合元素本身,系统只是依次把集合元素的值赋给迭代变量,因此在 foreach 循环中修改迭代变量的值也没有任何实际意义。

       同样,当使用 foreach 循环迭代访问集合元素时,该集合也不能被改变,否则将引发 ConcurrentModificationException 异常。举例:

 for (Object obj : objs) {
     // 此处的obj变量也不是集合元素本身
     String obj1 = (String) obj;
     System.out.println(obj1);
     if (obj1.equals("C语言中文网Java教程")) {
         // 下面代码会引发 ConcurrentModificationException 异常
         objs.remove(obj);
     }
 }

2.2 使用Java 8新增的Predicate操作Collection集合

       Java 8 起为 Collection 集合新增了一个 removeIf(Predicate filter) 方法,该方法将会批量删除符合 filter 条件的所有元素。该方法需要一个 Predicate 对象作为参数,Predicate 也是函数式接口,因此可使用 Lambda 表达式作为参数,使用 Predicate 可以充分简化集合的运算。例如:

 objs.removeIf(ele -> ((String) ele).length() < 12);// 使用Lambda表达式(目标类型是Predicate)过滤集合

2.3 Stream操作Collection集合

       Java 8 还新增了 Stream、IntStream、LongStream、DoubleStream 等流式 API,这些 API 代表多个支持串行和并行聚集操作的元素。上面 4 个接口中,Stream 是一个通用的流接口,而 IntStream、LongStream、 DoubleStream 则代表元素类型为 int、long、double 的流。

       Java 8 还为上面每个流式 API 提供了对应的 Builder,例如 Stream.Builder、IntStream.Builder、LongStream.Builder、DoubleStream.Builder,开发者可以通过这些 Builder 来创建对应的流。

独立使用 Stream 的步骤如下:

  • 使用 Stream 或 XxxStream 的 builder() 类方法创建该 Stream 对应的 Builder,例如:IntStream is = IntStream.builder().add(1).add(2).add(3).build();

  • 重复调用 Builder 的 add() 方法向该流中添加多个元素。

  • 调用 Builder 的 build() 方法获取对应的 Stream。

  • 调用 Stream 的聚集方法,例如:is.max.getAsInt()、is.min.getAsInt()、is.sum()、is.count()、is.average()、is.allMath(e->条件)、is.anyMatch(e->条件)、is.map(e->条件)等。 在上面 4 个步骤中,第 4 步可以根据具体需求来调用不同的方法,Stream 提供了大量的聚集方法供用户调用,具体可参考 Stream 或 XxxStream 的 API 文档。对于大部分聚集方法而言,每个 Stream 只能执行一次。

       Stream 提供了大量的方法进行聚集操作,这些方法既可以是“中间的”(intermediate),也可以是 "末端的"(terminal)。

  • 中间方法:中间操作允许流保持打开状态,并允许直接调用后续方法。上面程序中的 map() 方法就是中间方法。中间方法的返回值是另外一个流。

  • 末端方法:末端方法是对流的最终操作。当对某个 Stream 执行末端方法后,该流将会被“消耗”且不再可用。上面程序中的 sum()、count()、average() 等方法都是末端方法。

除此之外,关于流的方法还有如下两个特征。

  • 有状态的方法:这种方法会给流增加一些新的属性,比如元素的唯一性、元素的最大数量、保证元素以排序的方式被处理等。有状态的方法往往需要更大的性能开销。

  • 短路方法:短路方法可以尽早结束对流的操作,不必检查所有的元素。

       除此之外,Java 8 允许使用流式 API 来操作集合,Collection 接口提供了一个 stream() 默认方法,该方法可返回该集合对应的流,接下来即可通过流式 API 来操作集合元素。由于 Stream 可以对集合元素进行整体的聚集操作,因此 Stream 极大地丰富了集合的功能,例如:objs.stream().filter(ele -> ((String) ele).contains("C语言中文网")).count()。程序只要调用 Collection 的 stream() 方法即可返回该集合对应的 Stream,接下来就可通过 Stream 提供的方法对所有集合元素进行处理,这样大大地简化了集合编程的代码,这也是 Stream 编程带来的优势。

2.4 Java9新增的不可变集合

       Java 9 版本以前,假如要创建一个包含 6 个元素的 Set 集合,程序需要先创建 Set 集合,然后调用 6 次 add() 方法向 Set 集合中添加元素。Java 9 对此进行了简化,程序直接调用 Set、List、Map 的 of() 方法即可创建包含 N 个元素的不可变集合,这样一行代码就可创建包含 N 个元素的集合。不可变意味着程序不能向集合中添加元素,也不能从集合中删除元素。 例如:

 Set set = Set.of("Java", "Kotlin", "Go", "Swift");
 List list = List.of(34, -25, 67, 231);
 Map map = Map.of("语文", 89, "数学", 82, "英语", 92);
 Map map2 = Map.ofEntries(Map.entry("语文", 89), Map.entry("数学", 82), Map.entry("英语", 92));

3.List接口详解

       List 是一个有序、可重复的集合,集合中每个元素都有其对应的顺序索引。List 集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。List 集合默认按元素的添加顺序设置元素的索引,第一个添加到 List 集合中的元素的索引为 0,第二个为 1,依此类推。

       List 实现了 Collection 接口,它主要有两个常用的实现类:ArrayList 类和 LinkedList 类。

3.1 ArrayList类

       ArrayList 类实现了可变数组的大小,存储在内的数据称为元素。它还提供了快速基于索引访问元素的方式,对尾部成员的增加和删除支持较好。使用 ArrayList 创建的集合,允许对集合中的元素进行快速的随机访问,不过,向 ArrayList 中插入与删除元素的速度相对较慢。

ArrayList 类的常用构造方法有如下两种重载形式:

  • ArrayList():构造一个初始容量为 10 的空列表。

  • ArrayList(Collection<?extends E>c):构造一个包含指定 Collection 元素的列表,这些元素是按照该 Collection 的迭代器返回它们的顺序排列的。

       ArrayList 类除了包含 Collection 接口中的所有方法之外,还包括 List 接口中提供的如表 1 所示的方法。

注意:

  • 当调用 List 的 set(int index, Object element) 方法来改变 List 集合指定索引处的元素时,指定的索引必须是 List 集合的有效索引。例如集合长度为 4,就不能指定替换索引为 4 处的元素,也就是说这个方法不会改变 List 集合的长度。

  • 与 Set 不同的是,List 集合中存在 get() 方法,该方法可以通过索引来获取所对应的值,获取的值为 Object 类,因此需要将该值转换为所需类。

  • 在使用 List 集合时需要注意区分 indexOf() 方法和 lastIndexOf() 方法。前者是获得指定对象的最小索引位置,而后者是获得指定对象的最大索引位置。前提条件是指定的对象在 List 集合中有重复的对象,否则这两个方法获取的索引值相同。

3.2 LinkedList类

       LinkedList 类采用链表结构保存对象,这种结构的优点是便于向集合中插入或者删除元素。需要频繁向集合中插入和删除元素时,使用 LinkedList 类比 ArrayList 类效果高,但是 LinkedList 类随机访问元素的速度则相对较慢。这里的随机访问是指检索集合中特定索引位置的元素。

       LinkedList 类除了包含 Collection 接口和 List 接口中的所有方法之外,还特别提供了表 2 所示的方法。

ArrayList 类和 LinkedList 类的区别:

  • ArrayList 与 LinkedList 都是 List 接口的实现类,因此都实现了 List 的所有未实现的方法,只是实现的方式有所不同。

  • ArrayList 是基于动态数组数据结构的实现,访问元素速度优于 LinkedList。LinkedList 是基于链表数据结构的实现,占用的内存空间比较大,但在批量插入或删除数据时优于 ArrayList。

  • 对于快速访问对象的需求,使用 ArrayList 实现执行效率上会比较好。需要频繁向集合中插入和删除元素时,使用 LinkedList 类比 ArrayList 类效果高。

  • 不同的结构对应于不同的算法,有的考虑节省占用空间,有的考虑提高运行效率,对于程序员而言,它们就像是“熊掌”和“鱼肉”,不可兼得。高运行速度往往是以牺牲空间为代价的,而节省占用空间往往是以牺牲运行速度为代价的。

4. Set接口详解

       Set 集合类似于一个罐子,程序可以依次把多个对象“丢进”Set 集合,而 Set 集合通常不能记住元素的添加顺序。也就是说 Set 集合中的对象不按特定的方式排序,只是简单地把对象加入集合。Set 集合中不能包含重复的对象,并且最多只允许包含一个 null 元素。

       Set 实现了 Collection 接口,它主要有两个常用的实现类:HashSet 类和 TreeSet类。

4.1 HashSet 类

       HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时就是使用这个实现类。HashSet 是按照 Hash 算法来存储集合中的元素,因此具有很好的存取和查找性能。

HashSet 具有以下特点:

  • 不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。

  • HashSet 不是同步的,如果多个线程同时访问或修改一个 HashSet,则必须通过代码来保证其同步。

  • 集合元素值可以是 null。

       当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据该 hashCode 值决定该对象在 HashSet 中的存储位置。如果有两个元素通过 equals() 方法比较返回的结果为 true,但它们的 hashCode 不相等,HashSet 将会把它们存储在不同的位置,依然可以添加成功。

       也就是说,两个对象的 hashCode 值相等且通过 equals() 方法比较返回结果为 true,则 HashSet 集合认为两个元素相等。

       在 HashSet 类中实现了 Collection 接口中的所有方法。HashSet 类的常用构造方法重载形式如下:

  • HashSet():构造一个新的空的 Set 集合。

  • HashSet(Collection<? extends E>c):构造一个包含指定 Collection 集合元素的新 Set 集合。其中,“< >”中的 extends 表示 HashSet 的父类,即指明该 Set 集合中存放的集合元素类型。c 表示其中的元素将被存放在此 Set 集合中。

4.2 TreeSet 类

       TreeSet 类同时实现了 Set 接口和 SortedSet 接口。SortedSet 接口是 Set 接口的子接口,可以实现对集合进行自然排序,因此使用 TreeSet 类实现的 Set 接口默认情况下是自然排序的,这里的自然排序指的是升序排序。

       TreeSet 只能对实现了 Comparable 接口的类对象进行排序,因为 Comparable 接口中有一个 compareTo(Object o) 方法用于比较两个对象的大小。例如 a.compareTo(b),如果 a 和 b 相等,则该方法返回 0;如果 a 大于 b,则该方法返回大于 0 的值;如果 a 小于 b,则该方法返回小于 0 的值。

       表 1 列举了 JDK 类库中实现 Comparable 接口的类,以及这些类对象的比较方式。

注意:

  • 表面上看起来这些方法很多,其实很简单。因为 TreeSet 中的元素是有序的,所以增加了访问第一个、前一个、后一个、最后一个元素的方法,并提供了 3 个从 TreeSet 中截取子 TreeSet 的方法。

  • 在使用自然排序时只能向 TreeSet 集合中添加相同数据类型的对象,否则会抛出 ClassCastException 异常。如果向 TreeSet 集合中添加了一个 Double 类型的对象,则后面只能添加 Double 对象,不能再添加其他类型的对象,例如 String 对象等。

5. Map

       Map 是一种键-值对(key-value)集合,Map 集合中的每一个元素都包含一个键(key)对象和一个值(value)对象。用于保存具有映射关系的数据。

       Map 集合里保存着两组值,一组值用于保存 Map 里的 key,另外一组值用于保存 Map 里的 value,key 和 value 都可以是任何引用类型的数据。Map 的 key 不允许重复,value 可以重复,即同一个 Map 对象的任何两个 key 通过 equals 方法比较总是返回 false。

       Map 中的 key 和 value 之间存在单向一对一关系,即通过指定的 key,总能找到唯一的、确定的 value。从 Map 中取出数据时,只要给出指定的 key,就可以取出对应的 value。

       Map 接口主要有两个实现类:HashMap 类和 TreeMap 类。其中,HashMap 类按哈希算法来存取键对象,而 TreeMap 类可以对键对象进行排序。

       Map 接口中提供的常用方法如表 1 所示。

        Map 集合最典型的用法就是成对地添加、删除 key-value 对,接下来即可判断该 Map 中是否包含指定 key,也可以通过 Map 提供的 keySet() 方法获取所有 key 组成的集合,进而遍历 Map 中所有的 key-value 对。

5.1 Java遍历Map集合的四种方式

5.1.1 在 for 循环中使用entrySet()实现 Map 的遍历(最常见和最常用的)

 //获取键值对集合
 for (Map.Entry<String, String> entry : map.entrySet()) {
     String mapKey = entry.getKey();
     String mapValue = entry.getValue();
     System.out.println(mapKey + ":" + mapValue);
 }

5.1.2 使用 for-each 循环遍历 key 或者 values

一般适用于只需要 Map 中的 key 或者 value 时使用。性能上比 entrySet 较好。

 // 打印键集合
 for (String key : map.keySet()) {
     System.out.println(key);
 }
 // 打印值集合
 for (String value : map.values()) {
     System.out.println(value);
 }

5.1.3 使用迭代器(Iterator)遍历

 Iterator<Entry<String, String>> entries = map.entrySet().iterator();
 while (entries.hasNext()) {
     Entry<String, String> entry = entries.next();
     String key = entry.getKey();
     String value = entry.getValue();
     System.out.println(key + ":" + value);
 }

5.1.4 通过键找值遍历

这种方式的效率比较低,因为本身从键取值是耗时的操作。

 for(String key : map.keySet()){
     String value = map.get(key);
     System.out.println(key+":"+value);
 }

       注意:TreeMap 类的使用方法与 HashMap 类相同,唯一不同的是 TreeMap 类可以对键对象进行排序,这里不再赘述。

6.Collections类

       Collections 类是 Java 提供的一个操作 Set、List 和 Map 等集合的工具类。Collections 类提供了许多操作集合的静态方法,借助这些静态方法可以实现集合元素的排序、查找替换和复制等操作。下面介绍 Collections 类中操作集合的常用方法。

6.1 排序(正向和逆向)

Collections 提供了如下方法用于对 List 集合元素进行排序。

  • void reverse(List list):对指定 List 集合元素进行逆向排序(按放入顺序倒序输出)。

  • void shuffle(List list):对 List 集合元素进行随机排序(shuffle 方法模拟了“洗牌”动作)。

  • void sort(List list):根据元素的自然顺序对指定 List 集合的元素按升序进行排序(自然顺序即从小到大排序)。

  • void sort(List list, Comparator c):根据指定 Comparator 产生的顺序对 List 集合元素进行排序。

  • void swap(List list, int i, int j):将指定 List 集合中的 i 处元素和 j 处元素进行交换。

  • void rotate(List list, int distance):当 distance 为正数时,将 list 集合的后 distance 个元素“整体”移到前面;当 distance 为负数时,将 list 集合的前 distance 个元素“整体”移到后面。该方法不会改变集合的长度。

6.2 查找替换操作

Collections 还提供了如下常用的用于查找、替换集合元素的方法。

  • int binarySearch(List list, Object key):使用二分搜索法搜索指定的 List 集合,以获得指定对象在 List 集合中的索引。如果要使该方法可以正常工作,则必须保证 List 中的元素已经处于有序状态(二分查找前List中元素必须排好序,从小到大或从大到小)。

  • Object max(Collection coll):根据元素的自然顺序,返回给定集合中的最大元素(自然顺序即从小到大排序)。

  • Object max(Collection coll, Comparator comp):根据 Comparator 指定的顺序,返回给定集合中的最大元素。

  • Object min(Collection coll):根据元素的自然顺序,返回给定集合中的最小元素(自然顺序即从小到大排序)。

  • Object min(Collection coll, Comparator comp):根据 Comparator 指定的顺序,返回给定集合中的最小元素。

  • void fill(List list, Object obj):使用指定元素 obj 替换指定 List 集合中的所有元素。

  • int frequency(Collection c, Object o):返回指定集合中指定元素的出现次数。

  • int indexOfSubList(List source, List target):返回子 List 对象在父 List 对象中第一次出现的位置索引;如果父 List 中没有出现这样的子 List,则返回 -1。

  • int lastIndexOfSubList(List source, List target):返回子 List 对象在父 List 对象中最后一次出现的位置索引;如果父 List 中没有岀现这样的子 List,则返回 -1。

  • boolean replaceAll(List list, Object oldVal, Object newVal):使用一个新值 newVal 替换 List 对象的所有旧值 oldVal。

6.3 复制

       Collections 类的 copy() 静态方法用于将指定集合中的所有元素复制到另一个集合中。执行 copy() 方法后,目标集合中每个已复制元素的索引将等同于源集合中该元素的索引。copy() 方法的语法格式如下:

 void copy(List <? super T> dest,List<? extends T> src)

        其中,dest 表示目标集合对象,src 表示源集合对象。将源集合中的全部元素复制到目的集合对象中,目的集合对象中与源集合对象索引相同的元素会被覆盖。

       注意:目标集合的长度至少和源集合的长度相同,如果目标集合的长度更长,则不影响目标集合中的其余元素。如果目标集合长度不够而无法包含整个源集合元素,程序将抛出 IndexOutOfBoundsException 异常。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值