栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

万字手撕——Java集合源码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

万字手撕——Java集合源码

Java集合(一)——LinkedList和ArrayList源码 一、集合

集合主要分为两组(单列集合,双列集合)

  • 单列集合:存放单个元素

    • Collection:两个重要的接口 List Set
ArrayList arrayList = new ArrayList<>();
arrayList.add("jack");
arrayList.add("tom");

  • 双列集合:键值对的形式存元素K-V

    • Map
HashMap hashMap = new HashMap<>(64);
hashMap.put("NO1", "北京");
hashMap.put("NO2", "上海");

1.2、Conllection接口和常用方法 1.2.1、常用方法
  • add:添加单个元素
  • remove:删除指定元素
  • contains:查找元素是否存在
  • size:获取元素的个数
  • isEmpty:判断集合是否为空
  • clear:清空集合
  • addAll:添加多个元素
  • containsAll:查找多个元素是否都存在
  • removeAll:删除多个元素
public class CollectionMethod {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        // add:添加单个元素
        list.add("jack");
        // list.add(new Integer(10))
        list.add(10);
        list.add(true);
        System.out.println("List=" + list);

        // remove:删除指定元素
        // 通过下标删除元素
        list.remove(0);
        // 指定删除的元素
        list.remove(true);
        System.out.println("List=" + list);

        // contains:查找元素是否存在
        System.out.println(list.contains("jack"));

        // size:获取元素的个数
        System.out.println(list.size());

        // isEmpty:判断集合是否为空
        System.out.println(list.isEmpty());

        // clear:清空集合
        //list.clear();
        //System.out.println(list);

        // addAll:添加多个元素
        ArrayList arrayList = new ArrayList<>();
        arrayList.add("红楼梦");
        arrayList.add("三国演义");
        list.addAll(arrayList);
        System.out.println(list);

        // containsAll:查找多个元素是否都存在
        System.out.println(list.containsAll(arrayList));

        // removeAll:删除多个元素
        list.add("聊斋");
        list.removeAll(arrayList);
        System.out.println(list);
        
    }
}
 
1.2.2、Conllection接口遍历元素方式 
  • 使用Iterator(迭代器)
public class CollectionIterator {
    public static void main(String[] args) {
        Collection collection = new ArrayList<>();
        collection.add(new Book("三国演义", "罗贯中", 50));
        collection.add(new Book("小李飞刀", "古龙", 70.0));
        collection.add(new Book("红楼梦", "曹雪芹", 60.0));
//        System.out.println("collection = " + collection);

        // 得到迭代器
        Iterator iterator = collection.iterator();
        // 使用while循环遍历集合
        while (iterator.hasNext()) {
            Object obj =  iterator.next();
            System.out.println("obj = " + obj);
        }

        // 重置迭代器
        iterator = collection.iterator();
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println("obj = " + obj);
        }

    }

}

class Book {
    private String name;
    private String author;
    private double price;

    public Book(String name, String author, double price) {
        this.name = name;
        this.author = author;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + ''' +
                ", author='" + author + ''' +
                ", price=" + price +
                '}';
    }
}
 
  • 增强for循环:只能用来遍历集合和数组

    • 基本语法:for(元素类型 元素名 : 集合名或数组名) { 访问元素 }
public class CollectionFor {
    public static void main(String[] args) {
        Collection collection = new ArrayList<>();
        collection.add(new Book("三国演义", "罗贯中", 50));
        collection.add(new Book("小李飞刀", "古龙", 70.0));
        collection.add(new Book("红楼梦", "曹雪芹", 60.0));

        // 增强for
        // 增强for底层仍然是迭代器
        for (Object book : collection) {
            System.out.println("book = " + book);
        }

        // 增强for用在数组上
        int[] nums = {1, 6, 7, 9, 10};
        for (int i : nums) {
            System.out.println("i = " + i);
        }
    }
}
 
1.3、List接口和常用方法 
1.3.1、介绍 
  1. List集合类中元素有序、且可重复

  2. List集合中的每个元素有其对应的顺序索引,即支持索引。

  3. List容器中的元素对应一个整数的序号记载在容器中的位置,可以根据序号取出容器中的元素.

public class List_ {
    public static void main(String[] args) {

        // List集合类中元素有序、且可重复
        List list = new ArrayList<>();
        list.add("jack");
        list.add("mary");
        list.add("tom");
        list.add("chen");
        System.out.println("list = " + list);

        // List集合中的每个元素有其对应的顺序索引,即支持索引。
        System.out.println(list.get(2));
    }
}
 
1.3.2、常用方法 
  • void add(int index, Object ele):在index位置插入ele元素
  • boolean addAll(int index, Collection eles):从index位置开始将eles中的元素插入
  • Object get(int index):获取指定index位置的元素
  • int indexOf(Object obj):返回obj在当前集合中首次出现的位置
  • int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
  • Object remove(int index):移除指定index位置的元素,并返回此元素
  • Object set(int index, Object ele):设置指定index位置元素为ele
  • List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
public class ListMethod {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        //void add(int index, Object ele):在index位置插入ele元素
        list.add("张三丰");
        list.add("李小龙");
        // 在index = 1 的位置插入一个对象
        list.add(1, "宋江");
        System.out.println("list = " + list);
        //boolean addAll(int index, Collection eles):从index位置开始将eles中的元素插入
        List list2 = new ArrayList<>();
        list2.add("jack");
        list2.add("tom");
        list.addAll(1, list2);
        System.out.println("list = " + list);
        //Object get(int index):获取指定index位置的元素
        System.out.println(list.get(3));
        //int indexOf(Object obj):返回obj在当前集合中首次出现的位置
        System.out.println(list.indexOf("tom"));
        //int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
        list.add("tom");
        System.out.println("list = " + list);
        System.out.println(list.lastIndexOf("tom"));
        //Object remove(int index):移除指定index位置的元素,并返回此元素
        list.remove(0);
        System.out.println("List = " + list);
        //Object set(int index, Object ele):设置指定index位置元素为ele,相当于是替换
        list.set(1, "玛丽");
        System.out.println("List = " + list);
        // List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
        // 返回子集合范围[fromIndex, toIndex)
        List returnList = list.subList(0, 2);
        System.out.println("returnList = " + returnList);

    }

}
 
1.3.3、练习 
  • 添加十个以上的 String “hello”
  • 在2号位插入一个元素
  • 获取第6个元素
  • 删除第7个元素
  • 修改第8个元素
  • 使用迭代器遍历集合
public class ListExercise {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        // 添加十个以上的 String "hello"
        for (int i = 0; i < 12; i++) {
            list.add("hello" + i);
        }
        System.out.println("list = " + list);

        // 在2号位插入一个元素"chen"
        list.add(1, "chen");
        System.out.println("list = " + list);

        // 获取第6个元素
        System.out.println("第6个元素 = " + list.get(5));

        // 删除第7个元素
        list.remove(6);
        System.out.println("list = " + list);

        // 修改第8个元素
        list.set(7, "三国演义");
        System.out.println("list = " + list);

        // 使用迭代器遍历集合
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println("obj = " + obj);
        }
    }
}
 
1.3.4、List集合的三种遍历方式 
  • 迭代器Iterator
  • 增强for
  • 普通for
public class ListFor {
    public static void main(String[] args) {

        // List 接口的实现子类 Vector LinkedList
        // List list = new ArrayList<>();
         List list = new LinkedList<>();
        // List list = new Vector<>();
        list.add("jack");
        list.add("tom");
        list.add("天龙八部");
        list.add("北京烤鸭");

        // 遍历
        // 1.迭代器
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println("obj = " + obj);
        }
        System.out.println("=================");
        //2.增强for循环
        for (Object x : list) {
            System.out.println(x);
        }

        System.out.println("================");
        //3.普通for循环
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

    }
}
 
1.3.5、List排序练习 

Book类

public class Book {
    private String name;
    private String author;
    private int price;

    public Book(String name, String author, int price) {
        this.name = name;
        this.author = author;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "名称:"+ name +"tt价格:" + price+ "tt作者:" + author;
    }
}

main:

public class ListExercise2 {
    public static void main(String[] args) {

        // List list = new Vector<>();
        List list = new ArrayList<>();
        // List list = new LinkedList<>();
        list.add(new Book("红楼梦", "曹雪芹", 70));
        list.add(new Book("西游记", "吴承恩", 10));
        list.add(new Book("水浒传", "施耐庵", 90));
        list.add(new Book("三国志", "罗贯中", 80));
        // 遍历
        for (Object o : list) {
            System.out.println(o);
        }

        // 冒泡排序
        sort(list);
        System.out.println("=========");

        // 排序后遍历
        for (Object o : list) {
            System.out.println(o);
        }

    }
    public static void sort(List list) {
        for (int i = 0; i < list.size() - 1; i++) {
            for (int j = 0; j < list.size() - 1 - i; j++) {
                // 取出对象Book
                Book book1 = (Book) list.get(j);
                Book book2 = (Book) list.get(j + 1);
                if (book1.getPrice() > book2.getPrice()) {
                    list.set(j, book2);
                    list.set(j + 1, book1);
                }
            }
        }
    }
}
 
1.4、ArrayList底层结构和源码分析 
1.4.1、注意事项 
  1. ArrayList可以存放空值null
  2. ArrayList是由数组来实现数据存储的
  3. ArrayList是线程不安全的(执行效率高),多线程情况下,不建议使用ArrayList
public class ArrayListDetail {
    public static void main(String[] args) {
        ArrayList arrayList = new ArrayList<>();
        arrayList.add(null);
        arrayList.add("jack");
        arrayList.add(null);

        System.out.println("arrayList = " + arrayList);
    }
}
1.4.2、ArrayList扩容机制
  1. ArrayList中维护一个Object类型的数组elementData transient Object[] elementData;
  2. transient :表示瞬间,短暂的

  1. 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如需再次扩容,则扩容elementData为1.5倍。

  1. 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如需扩容,则直接扩容elementData为1.5倍。

1.4.3、ArrayList源码 一、当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如需再次扩容,则扩容elementData为1.5倍。

演示代码

public class ArrayListSource {
    public static void main(String[] args) {
        // 使用午餐构造器创建ArrayList对象
        ArrayList list = new ArrayList<>();
        // ArrayList list = new ArrayList<>(8);
        // 使用for给list集合添加 1-10数据
        for (int i = 1; i <= 10; i++) {
            list.add(i);
        }
        // 使用for给list集合添加11-15数据
        for (int i = 11; i <= 15; i++) {
            list.add(i);
        }

        list.add(200);
        list.add(100);
    }

}
1.5、Vector底层结构和源码分析 1.5.1、基本介绍
  1. Vector类的定义说明

  1. Vector底层也是一个对象数组,protected Object[] elementData;
  2. Vector是线程同步的,即线程安全,Vector类的操作方法带有synchronized

1.5.2、Vector底层和ArrayList的比较
底层结构版本线程安全(同步)效率扩容倍数
ArrayList可变数组JDK1.2不安全,效率高如果有参构造1.5倍如果是无参1.第一次102.从第二次开始按照1.5倍
Vector可变数组JDK1.0安全效率高如果是无参,默认10,满后直接按2倍扩容如果指定大小,则每次直接按2倍扩容
1.5.3、源码解读 一、创建Vector对象时使用无参构造器源码
public class Vector_ {
    public static void main(String[] args) {
        // 无参构造器
        Vector vector = new Vector<>();
        for (int i = 0; i < 10; i++) {
            vector.add(i);
        }
        vector.add(100);
        System.out.println("vector = " + vector);
        // 源码解读
        // 1. new Vector() 底层
        
    }
}
二、分析图

1.6、LinkedList底层结构 1.6.1、说明
  1. LinkedList实现了双向链表和双端队列特点
  2. 可以添加任意元素(元素可以重复),包括null
  3. 线程不安全,没有实现同步
1.6.2、LinkedList的底层操作机制
  1. LinkedList底层维护了一个双向链表
  2. LinkedList中维护了两个属性first和last分别指向首节点和尾节点
  3. 每个节点(Node对象),里面有维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表
  4. LinkedList的元素添加和删除,不是通过数组完成的,相对来说效率较高
  5. 模拟简单的双向链表
public class LinkedList01 {
    public static void main(String[] args) {
        // 模拟简单的双向链表

        Node jack = new Node("jack");
        Node tom = new Node("tom");
        Node chen = new Node("chen");

        // 连接三个节点,形成双向链表
        // jack -> tom -> chen
        jack.next = tom;
        tom.next = chen;
        // chen -> tom -> jack
        chen.prev = tom;
        tom.prev = jack;

        // 让first引用指向jack,就是双向链表的头节点
        Node first = jack;
        // 让last引用指向chen,就是双向链表的尾节点
        Node last = chen;

        // 遍历 从头到尾遍历
        while (true) {
            if (first == null) {
                break;
            }
            // 输出信息
            System.out.println(first);
            first = first.next;
        }

        // 遍历 从尾到头遍历
        System.out.println("===从尾到头遍历===");
        while (true) {
            if (last == null) {
                break;
            }
            // 输出信息
            System.out.println(last);
            last = last.prev;
        }

        // 添加元素

        // 1.创建一个Node结点, name 是张飞
        Node zf = new Node("张飞");
        zf.next = chen;
        zf.prev = tom;
        chen.prev = zf;
        tom.next = zf;

        // 让first 再次指向jack
        first = jack;
        System.out.println("===从头到尾遍历===");
        while (true) {
            if (first == null) {
                break;
            }
            // 输出信息
            System.out.println(first);
            first = first.next;
        }

    }
}


class Node {
    
    public Object item;
    
    public Node next;
    
    public Node prev;

    public Node(Object name) {
        this.item = name;
    }
    public String toString() {
        return "Node name = " + item;
    }
}
1.6.3、LinkedList底层源码 1.6.3.1、添加元素
  • linkedList.add(1);
// 1、LinkedList linkedList = new LinkedList<>();
   public LinkedList() {}
// 2、这是LinkedList 的属性first = null last = null
// 3、执行add方法
   public boolean add(E e) {
       linkLast(e);
       return true;
   }
// 4、将新的结点,加入到双向链表的最后
   void linkLast(E e) {
       final Node l = last;
       final Node newNode = new Node<>(l, e, null);
       last = newNode;
       if (l == null)
           first = newNode;
       else
           l.next = newNode;
       size++;
       modCount++;
    }
  • 流程图

  • 执行 add 方法

  • 执行 linkList

1.6.3.2、删除元素
  • linkedList.remove();
// 1、linkedList.remove();// 默认删除第一个元素
// 2、执行 removeFirst() 方法
    public E remove() {
        return removeFirst();
    }
// 3、执行
    public E removeFirst() {
        final Node f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }
// 4、执行  unlinkFirst, 将 f 指向的双向链表的第一个结点拿掉
    private E unlinkFirst(Node f) {
        // assert f == first && f != null;
        final E element = f.item;
        final Node next = f.next;
        f.item = null;
        f.next = null; // help GC
        first = next;
        if (next == null)
            last = null;
        else
            next.prev = null;
        size--;
        modCount++;
        return element;
    }
  • 流程图

1.6.3.3、LinkedList的其他方法
  • get()
  • remove(int index)
  • set(int index)

等等的源码都可以依照以上方法进行追溯。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号