链表以及map集合

66 阅读6分钟

12.2.5 链表

1、链表是一种数据结构
(1)单向链表
(2)双向链表
(3)循环链表
​
数组的元素是连续存储的,位置是相邻的。
链表:元素不要求连续存储。
    结点:包含数据(对象)及其关系。
    
​
2、源码中LinkedList也是双向链表。

day0401_01数组与链表的对比分析.png

12.2.5 自定义双向链表

​
​
import java.util.Iterator;
​
/*
尝试自定义双向链表(部分方法)
 */
public class PairLinkedList<E> implements Iterable<E>{
    private PairNode<E> first;
    private PairNode<E> last;
    private int size;
​
    public void add(E e){
       // (1)先创建结点把e包装起来
        PairNode<E> newNode = new PairNode<>(last, e, null);
​
        //(2)分情况
        if(first == null){//链表是空的  first == null 或  last == null
            first = newNode;
        }else{
            last.next = newNode;
        }
​
        //(3)新结点链表的最后一个结点
        last = newNode;
​
        //(4)元素个数增加
        size++;
    }
​
    public void add(int index, E e){
        //检查index的合法性
        if(index < 0 || index > size){
            throw new IndexOutOfBoundsException();
        }
        //确定index对应的结点
        PairNode<E> node = first;
        for(int i = 0; i< index; i++){
            node = node.next;
        }
​
        if(node == null){//末尾添加
            add(e);
        }else {//非末尾位置添加
            //在该结点的前面插入新的结点
            // (1)先创建结点把e包装起来
            PairNode<E> newNode = new PairNode<>(node.previous, e, node);
​
            if(node.previous == null){//插入位置是头部
                first = newNode;
            }else{//插入位置非头部
                node.previous.next = newNode;
            }
            node.previous = newNode;
​
            size++;
        }
    }
​
    public void remove(Object obj){
        //找到obj对应的node
        PairNode<E>  node = first;
        if(obj == null){
            while(node != null){
                if(node.data == null){
                    break;
                }
                node = node.next;
            }
        }else{
            while(node != null){
                if(obj.equals(node.data)){
                    break;
                }
                node = node.next;
            }
        }
​
        if(node == null){//被删除结点不存在,不是删除
            return;
        }
​
        if(node.previous == null){//头部删除
            node.next.previous = null;
            //或 node.next.previous  = node.previous;
            first = node.next;
        }else {//非头部删除
            node.previous.next = node.next;
​
            if (node.next == null) {//尾部删除
                last = node.previous;
            } else {//非尾部删除
                node.next.previous = node.previous;
            }
        }
​
        node.previous = null;
        node.next = null;
        node.data = null;
        size--;
    }
​
​
​
    @Override
    public Iterator<E> iterator() {
        return new Itr();
    }
​
    private class Itr implements Iterator<E>{
        PairNode<E> node = first;
​
        @Override
        public boolean hasNext() {
            return node != null;
        }
​
        @Override
        public E next() {
            E data = node.data;
            node = node.next;
            return data;
        }
    }
​
    private static class PairNode<E>{
        PairNode<E> previous;
        E data;
        PairNode<E> next;
​
        PairNode(PairNode<E> previous, E data, PairNode<E> next) {
            this.previous = previous;
            this.data = data;
            this.next = next;
        }
    }
}
​
​
import org.junit.Test;
​
public class TestPairLinkedList {
    @Test
    public void test1(){
        PairLinkedList<String> list = new PairLinkedList<>();
        list.add("hello");
        list.add("world");
        list.add("java");
        list.add("atguigu");
​
        for (String s : list) {
            System.out.println(s);
        }
    }
​
    @Test
    public void test2(){
        PairLinkedList<String> list = new PairLinkedList<>();
        list.add("hello");
        list.add("world");
        list.add("java");
        list.add("atguigu");
​
        list.add(2,"haha");
​
        for (String s : list) {
            System.out.println(s);
        }
    }
​
    @Test
    public void test3(){
        PairLinkedList<String> list = new PairLinkedList<>();
        list.add(0,"hello");
        list.add(0,"world");
        list.add(1,"java");
        list.add(2,"atguigu");
        for (String s : list) {
            System.out.println(s);
        }
    }
​
​
    @Test
    public void test4(){
        PairLinkedList<String> list = new PairLinkedList<>();
        list.add("hello");
        list.add("world");
        list.add("java");
        list.add("atguigu");
​
        list.remove("world");
        list.remove("hello");
        list.remove("atguigu");
​
        for (String s : list) {
            System.out.println(s);
        }
    }
}
​

day0401_02双向链表添加结点(默认末尾位置).png day0401_03双向链表的遍历.png

day0401_05双向链表插入(末尾位置).png

day0401_06双向链表插入(头部位置).png

day0401_04双向链表的插入(中间位置).png

day0401_07双向链表的结点查找.png

day0401_08双向链表的删除(中间位置).png

day0401_09双向链表的删除(末尾位置).png

day0401_10双向链表的删除(头部位置).png

12.2.6 自定义单向链表

import java.util.Iterator;
​
public class SingleLinkedList<E> implements Iterable<E>{
    private SingleNode<E> first;
    private int size;
​
    public void add(E e){
        //创建结点
        SingleNode<E> newNode = new SingleNode<>(e,null);
​
        if(first == null){//链表是空额
            first = newNode;
        }else {//链表非空
            //查找末尾结点
            SingleNode<E> node = first;
            while (node.next != null) {
                node = node.next;
            }
​
            //把新结点连接到node的后面
            node.next = newNode;
        }
​
        //元素个数增加
        size++;
    }
​
    @Override
    public Iterator<E> iterator() {
        return new Itr();
    }
​
    private class Itr implements Iterator<E>{
        SingleNode<E> node = first;
​
        @Override
        public boolean hasNext() {
            return node != null;
        }
​
        @Override
        public E next() {
            E data = node.data;
            node = node.next;
            return data;
        }
    }
​
    private static class SingleNode<E>{
        E data;
        SingleNode<E> next;
​
        SingleNode(E data, SingleNode<E> next) {
            this.data = data;
            this.next = next;
        }
    }
}
​
​
import org.junit.Test;
​
public class TestSingleLinkedList {
    @Test
    public void test1(){
        SingleLinkedList<String> list = new SingleLinkedList<>();
        list.add("hello");
        list.add("java");
        list.add("world");
​
        for (String s : list) {
            System.out.println(s);
        }
    }
}
​

day0401_11单向链表的添加.png

day0401_12单向链表的遍历.png

day0401_13单向链表定位末尾位置.png

12.2.7 链表与动态数组的对比

 动态数组和链表的特点的对比
 (1)底层结构
 数组的元素是连续存储的,元素的位置是相邻的,元素的访问可以快速的根据下标进行元素访问。
 链表:元素不要求连续存储,而是通过“结点”将元素“串联”起来。
​
 (2)性能的对比
 A:根据下标访问,数组效率非常高,链表相对慢一点。
 B:添加元素的效率
①末尾位置添加元素,动态数组更快一点(虽然数组需要扩容,但是反而更快),链表反而更慢(因为链表需要创建结点)
②任意位置添加元素,动态数组更快一点(虽然数组需要扩容,但是反而更快),链表反而更慢(因为链表需要创建结点)(测试目标1000000个对象)
③任意位置添加元素,动态数组更快一点(虽然数组需要扩容,但是反而更快),链表反而更慢(因为链表需要创建结点)(测试目标10000个对象)
C:删除元素的效率
①根据下标的删除,动态数组更快一点,链表反而更慢(因为链表需要统计下标)
②末尾位置删除,动态数组更快一点,链表反而更慢(因为链表需要清理结点,处理last)
③根据目标的删除,动态数组和链表比较接近 
     对象少,链表快
     对象多,数组快
package com.atguigu.link;
​
import org.junit.Test;
​
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Random;
​
public class TestTime {
    @Test
    public void test1() {
        long start = System.currentTimeMillis();
        ArrayList<Double> list = new ArrayList<>();
        for (int i = 1; i <= 10000000; i++) {
            list.add(Math.random());
        }
        long end = System.currentTimeMillis();
        System.out.println("ArrayList末尾添加耗时:" + (end - start));//457毫秒
​
        long memory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
        System.out.println("ArrayList末尾添加占用内存: " + memory);//361114168字节
    }
​
    @Test
    public void test2(){
        long start = System.currentTimeMillis();
        LinkedList<Double> list = new LinkedList<>();
        for(int i=1; i<=10000000; i++){
            list.add(Math.random());
        }
        long end = System.currentTimeMillis();
        System.out.println("LinkedList末尾添加耗时:" + (end-start));//4194毫秒
​
        long memory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
        System.out.println("LinkedList末尾添加占用内存: " + memory);//498723056字节
    }
​
    @Test
    public void test3(){
        long start = System.currentTimeMillis();
        ArrayList<Double> list = new ArrayList<>();
        Random random = new Random();
        for (int i = 1; i <= 10000; i++) {
            int index = Math.abs(random.nextInt());
            index = list.size() != 0 ? index%list.size() : 0;
            list.add(index,Math.random());
        }
        long end = System.currentTimeMillis();
        System.out.println("ArrayList插入耗时:" + (end - start));//25239毫秒(100万)、7毫秒(1万)
​
        long memory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
        System.out.println("ArrayList插入占用内存: " + memory);//54395728字节
    }
​
    @Test
    public void test4(){
        long start = System.currentTimeMillis();
        LinkedList<Double> list = new LinkedList<>();
        Random random = new Random();
        for (int i = 1; i <= 10000; i++) {
            int index = Math.abs(random.nextInt());
            index = list.size() != 0 ? index%list.size() : 0;
            list.add(index,Math.random());
​
        }
        long end = System.currentTimeMillis();
        System.out.println("LinkedList插入耗时:" + (end-start));//85(1万)
​
        long memory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
        System.out.println("LinkedList插入占用内存: " + memory);//13439648
    }
​
    @Test
    public void test5() {
        ArrayList<Double> list = new ArrayList<>();
        for (int i = 1; i <= 10000000; i++) {
            list.add(Math.random());
        }
​
        long start = System.currentTimeMillis();
        //删除
        for (int i = list.size()-1; i >=0 ; i--) {
            list.remove(i);
        }
​
        long end = System.currentTimeMillis();
        System.out.println("ArrayList末尾删除耗时:" + (end - start));//17(10000000个对象)
​
        long memory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
        System.out.println("ArrayList末尾删除耗占用内存: " + memory);//361138184
    }
​
    @Test
    public void test6(){
        LinkedList<Double> list = new LinkedList<>();
        for(int i=1; i<=10000000; i++){
            list.add(Math.random());
        }
​
        long start = System.currentTimeMillis();
        //删除
        for (int i = list.size()-1; i >=0 ; i--) {
            list.remove(i);
        }
​
        long end = System.currentTimeMillis();
        System.out.println("LinkedList末尾删除耗时:" + (end-start));//118毫秒
​
        long memory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
        System.out.println("LinkedList末尾删除占用内存: " + memory);//498733848
    }
​
    @Test
    public void test7() {
        ArrayList<Double> list = new ArrayList<>();
        for (int i = 1; i <= 100000; i++) {
            list.add(Math.random());
        }
​
        long start = System.currentTimeMillis();
        //删除
        Random random = new Random();
        for (int i = 1; i <= 10000; i++) {
            int index = Math.abs(random.nextInt());
            index = list.size() != 0 ? index % list.size() : 0;
            list.remove(index);
        }
​
        long end = System.currentTimeMillis();
        System.out.println("ArrayList非末尾删除耗时:" + (end - start));//42毫秒
​
        long memory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
        System.out.println("ArrayList非末尾删除耗占用内存: " + memory);//361138184
    }
​
    @Test
    public void test8(){
        LinkedList<Double> list = new LinkedList<>();
        for(int i=1; i<=100000; i++){
            list.add(Math.random());
        }
​
        long start = System.currentTimeMillis();
        //删除
        Random random = new Random();
        for (int i = 1; i <= 10000; i++) {
            int index = Math.abs(random.nextInt());
            index = list.size() != 0 ? index % list.size() : 0;
            list.remove(index);
        }
​
        long end = System.currentTimeMillis();
        System.out.println("LinkedList非末尾删除耗时:" + (end-start));//583毫秒
​
        long memory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
        System.out.println("LinkedList非末尾删除占用内存: " + memory);//18808352
    }
​
    @Test
    public void test9() {
        ArrayList<Double> list = new ArrayList<>();
        for (int i = 1; i <= 100000; i++) {
            list.add(Math.random());
        }
​
        long start = System.currentTimeMillis();
        //删除
        for(int i=1; i<=10000; i++) {
            list.remove(Math.random());
        }
​
        long end = System.currentTimeMillis();
        System.out.println("ArrayList非末尾,查询对象删除耗时:" + (end - start));//1218
​
        long memory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
        System.out.println("ArrayList末尾,查询对象删除耗占用内存: " + memory);//18808376
    }
​
    @Test
    public void test10(){
        LinkedList<Double> list = new LinkedList<>();
        for(int i=1; i<=100000; i++){
            list.add(Math.random());
        }
​
        long start = System.currentTimeMillis();
        //删除
        for(int i=1; i<=10000; i++){
            list.remove(Math.random());
        }
​
        long end = System.currentTimeMillis();
        System.out.println("LinkedList非末尾删除耗时:" + (end-start));//2732
​
        long memory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
        System.out.println("LinkedList末尾删除占用内存: " + memory);//21492728
    }
}
​

12.3 Map集合

12.3.1 Map接口

1、Java中的集合分为两大类:
(1)Collection系列:存储一组对象,里面的对象是单个、单个的
(2)Map系列:存储一组键值对(key,value),又称为映射关系
    A:一个key可以映射到一个value;
    B:key不能重复,但是value允许重复
    C:key,value可以是任意引用数据类型
​
2、java.util.Map<K,V>接口(必须掌握)
(1)增加
V put(K key, V value):添加一对键值对
void putAll(Map<? extends K,? extends V> m):添加一组键值对
​
(2)删除
void clear():清空
V remove(Object key) :根据key删除一对(key,value)
​
(3)修改
JDK1.8之前,要替换value,需要重新put
JDK1.8之后:
    V replace(K key, V value):只要key匹配就行,用新的value替换旧的value
    boolean replace(K key, V oldValue, V newValue) :必须匹配(key,oldValue),再用 新的value替换旧的value
    void replaceAll(BiFunction<? super K,? super V,? extends V> function):根据function指定的操作,替换所有满足的value
​
(4)查询
boolean containsKey(Object key)  :判断某个key是否存在
boolean containsValue(Object value)  :判断某个value是否存在
int size() :键值对的数量
boolean isEmpty()  :是否为空
​
V get(Object key) :根据key获取value(常用)
​
(5)遍历
A:Set<K> keySet() :遍历所有的key。(因为key不会重复,所以所有的key组成一个set集合)
B:Collection<V> values() :遍历所有的value。(因为value可能重复,所以所有的value组成一个Collection的某集合)
C:Set<Map.Entry<K,V>> entrySet() :遍历所有的(key,value)
        (因为key不会重复,所以所有的(key,value)组成一个set集合)
        (key,value)在map内部其实是以Entry对象存在。可以把Entry比喻为链表的结点。
        Entry是Map接口中的内部接口。
D:Java8版本,增加了一个forEach方法
    void forEach(BiConsumer<? super K,? super V> action)

12.3.2 Map实现类

3、Map接口的实现类:
(1)HashMap<K,V>:哈希表,key不可重复,完全无序
(2)TreeMap<K,V>:红黑树,key不可重复,按照key的大小顺序,所以它会依赖于Comparable接口和Comparator接口。
(3)LinkedHashMap<K,V>:key不可重复,按照(key,value)的添加顺序
        LinkedHashMap是HashMap的子类。比HashMap多加了一条双向链表,记录它们的添加顺序。
(4)Hashtable<K,V>:哈希表,key不可重复,完全无序
        Hashtable:旧版,线程安全的,不支持key,value为null
        HashMap:新版,线程不安全的,支持key,value为null
(5)Properties:属性表,key不可重复,完全无序
        Properties是Hashtable的子类,而且它的key和value都是String类型。
package com.atguigu.map;
​
import org.junit.Test;
​
import java.io.IOException;
import java.text.Collator;
import java.util.*;
​
public class TestMapImpl {
    @Test
    public void test1(){
        HashMap<String, String> map = new HashMap<>();
        map.put("一", "张三");
        map.put("二", "李四");
        map.put("三", "王五");
        map.put("四", null);
        map.put(null, "熊大");
​
        System.out.println(map);
        //{一=张三, null=熊大, 三=王五, 四=null, 二=李四}
    }
​
    @Test
    public void test2(){
        Hashtable<String, String> map = new Hashtable<>();
        map.put("一", "张三");
        map.put("二", "李四");
        map.put("三", "王五");
//        map.put("四", null);
//        map.put(null, "熊大");
​
        System.out.println(map);//{一=张三, 三=王五, 二=李四}
    }
​
    @Test
    public void test3(){
        TreeMap<String, String> map = new TreeMap<>();
        map.put("yi", "张三");
        map.put("er", "李四");
        map.put("san", "王五");
​
        System.out.println(map);//{er=李四, san=王五, yi=张三}
    }
​
    @Test
    public void test4(){
        TreeMap<String, String> map = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return Collator.getInstance(Locale.CHINA).compare(o1,o2);
            }
        });
        map.put("一", "张三");
        map.put("二", "李四");
        map.put("三", "王五");
​
​
        System.out.println(map);//{二=李四, 三=王五, 一=张三}
    }
​
    @Test
    public void test5(){
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        map.put("一", "张三");
        map.put("二", "李四");
        map.put("三", "王五");
        System.out.println(map);//{一=张三, 二=李四, 三=王五}
    }
​
    @Test
    public void test6(){
        Properties properties = new Properties();
        //虽然也支持put,但是更推荐setProperty
        properties.setProperty("user","chai");
        properties.setProperty("password","123456");
        System.out.println(properties);
    }
​
    @Test
    public void test7(){
        Properties properties = System.getProperties();
        Set<Map.Entry<Object, Object>> entries = properties.entrySet();
        for (Map.Entry<Object, Object> entry : entries) {
            System.out.println(entry);
        }
    }
​
    @Test
    public void test8() {
        Properties properties = System.getProperties();
        String value = properties.getProperty("file.encoding");
        System.out.println(value);
    }
​
    @Test
    public void test9() throws IOException {
        Properties properties = new Properties();
        properties.load(ClassLoader.getSystemResourceAsStream("jdbc.properties"));
        System.out.println(properties);
    }
​
    @Test
    public void test10(){
        HashMap<Integer, String> map = new HashMap<>();
        map.put(155841, "张三");
        map.put(2222, "李四");
        map.put(3333, "王五");
​
        System.out.println(map);
    }
​
}
​

12.3.3 Map与Set

4MapSet
Set是基于Map结构又再次封装,抽象出来的一类集合。
把Map中所有的key抽出来构成了“元素不可重复的集”。
常见的SetHashSet:底层是HashMap
TreeSet:底层是TreeMap
LinkedHashSet:底层是LinkedHashMap

12.4 集合工具类Collections

1、集合工具类:java.util.Collections
​
2、API
- public static <T> boolean addAll(Collection<? super T> c,T... elements)
        将所有指定元素添加到指定 collection 中。
​
- public static <T> int binarySearch(List<? extends Comparable<? super T>> list,T key)
        在List集合中查找某个元素的下标,但是List的元素必须是T或T的子类对象,而且必须是可比较大小的,即支持自然排序的。而且集合也事先必须是有序的,否则结果不确定。
- public static <T> int binarySearch(List<? extends T> list,T key,Comparator<? super T> c)
        在List集合中查找某个元素的下标,但是List的元素必须是T或T的子类对象,而且集合也事先必须是按照c比较器规则进行排序过的,否则结果不确定。
​
- public static <T extends Comparable<? super T>> void sort(List<T> list)根据元素的自然顺序对指定 List 集合元素按升序排序
- public static <T> void sort(List<T> list,Comparator<? super T> c)根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
​
- public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)在coll集合中找出最大的元素,集合中的对象必须是T或T的子类对象,而且支持自然排序
- public static <T> T max(Collection<? extends T> coll,Comparator<? super T> comp)在coll集合中找出最大的元素,集合中的对象必须是T或T的子类对象,按照比较器comp找出最大者
​
​
- public static void reverse(List<?> list)反转指定列表List中元素的顺序。
- public static void shuffle(List<?> list) List 集合元素进行随机排序,类似洗牌
- public static void swap(List<?> list,int i,int j)将指定 list 集合中的 i 处元素和 j 处元素进行交换
​
- public static int frequency(Collection<?> c,Object o)返回指定集合中指定元素的出现次数
​
public static <T> void copy(List<? super T> dest,List<? extends T> src)将src中的内容复制到dest中,会覆盖原来的元素
​
public static <T> boolean replaceAll(List<T> list,T oldVal,T newVal):使用新值替换 List 对象的所有旧值
​
​
package com.atguigu.collections;
​
import org.junit.Test;
​
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
​
public class TestCollections {
    @Test
    public void test1(){
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "hello","java","world","hello");
        System.out.println(list);
    }
​
    @Test
    public void test2(){
        HashSet<String> list = new HashSet<>();
        Collections.addAll(list, "hello","java","world","hello");
        System.out.println(list);
    }
​
    @Test
    public void test3(){
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 4,5,1,2,6,9,41);//没有按照大小排序
​
        int index = Collections.binarySearch(list, 1);
        System.out.println(index);
    }
​
    @Test
    public void test4(){
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 1,2,4,5,6,9,41);//按照大小排序
​
        int index = Collections.binarySearch(list, 1);
        System.out.println(index);//0
    }
​
    @Test
    public void test5(){
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 4,5,1,2,6,9,41);//没有按照大小排序
​
        Collections.sort(list);
​
        System.out.println(list);//[1, 2, 4, 5, 6, 9, 41]
    }
​
    @Test
    public void test6(){
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 4,5,1,2,6,9,41);//没有按照大小排序
​
        Integer max = Collections.max(list);
        System.out.println(max);//41
    }
​
    @Test
    public void test7(){
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 1,2,4,5,6,9,41);
​
        System.out.println("反转之前:" + list);
        Collections.reverse(list);
        System.out.println("反转之后:" + list);
        Collections.shuffle(list);
        System.out.println("洗牌之后:" + list);
    }
​
    @Test
    public void test8(){
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 41,2,41,5,6,9,41);
        int count = Collections.frequency(list, 41);
        System.out.println(count);
    }
​
    @Test
    public void test9(){
        ArrayList<Integer> list1 = new ArrayList<>();
        Collections.addAll(list1, 1,2,4,5,6,9,41);
​
        ArrayList<Integer> list2 = new ArrayList<>();
        Collections.addAll(list2, 8,8,8,8,8,8);
​
        Collections.copy(list1, list2);
        System.out.println(list1);//[8, 8, 8, 8, 8, 8, 41]
        System.out.println(list2);//[8, 8, 8, 8, 8, 8]
    }
​
    @Test
    public void test10(){
        ArrayList<Integer> list1 = new ArrayList<>();
        Collections.addAll(list1, 1,2,4,5,6,9,41);
​
        ArrayList<Integer> list2 = new ArrayList<>();
        Collections.addAll(list2, 8,8,8,8,8,8);
​
        list1.addAll(list2);
        System.out.println(list1);//[1, 2, 4, 5, 6, 9, 41, 8, 8, 8, 8, 8, 8]
​
    }
​
    @Test
    public void test11(){
        ArrayList<Integer> list1 = new ArrayList<>();
        Collections.addAll(list1, 1,2,4,5);
​
        ArrayList<Integer> list2 = new ArrayList<>();
        Collections.addAll(list2, 8,8,8,8,8,8);
​
        Collections.copy(list1, list2);// Source does not fit in dest 错误
​
    }
​
}
​

12.5 集合框架图

集合框架图.jpg