java-01源码篇-04 Java集合-02-List接口(三)之多学一点系列

一,简介

        如上图所示,前面的章节一和章节二主要是将List, AbstractList<E>分支下的讲解完毕;还有就是剩下红框框的内容没有讲解了。

第一章链接:java-01基础篇-04 Java集合-02-List接口(一)

第二章链接:java-01基础篇-04 Java集合-02-List接口(二)

        左边红圈圈的子接口,这些接口都是Java 处理XML文档所建立的接口;由于在JDK9之后对于java的类库提供模块化的管理方式;对于常见的类库都放在java.base 模块里面,该模块里面有集合,线程,IO等等常见类库;而对于java处理XML文档相关的业务自然也是有对应的模块所管理着,该模块名称叫做“java.xml”;如下图所示:

        JDK9模块化之后,对于其他模块的引用,并不能直接引用,直接引用或者导入进行会爆红,表示没有这个模块名称;无法直接使用。需要将指定的模块进行导出才能使用

        引用指定的模块这样,才不会报错! 如果没有引用;则如下图所示

       ObjectList, LSInputList, StringList, XSObjectList, ByteList,XSNamespaceItemList, ShortList这些类都是属于java.xml 模块里面的,需要进行手工导入,在JDK9的模块化管理;除了java.base 模块不用导入以外,其他模块都需要进行导入;就像java.lang 包不需要进行导入一样;

         如果需要使用 java.xml 模块,则需要使用JDK9模块化提供一些指令,将java.xml 模块进行导出,这些就是可以使用了

1.1 【StringList - 案例】

package org.toast.xml;


import com.sun.org.apache.xerces.internal.impl.xs.util.StringListImpl;

import java.util.ArrayList;
import java.util.List;

/**
 * @author toast
 * @time 2024/4/25
 * @remark
 */
public class TestStringList {
    private static String url = "file:///G:/work-space/WORK_GROUP/java-basics/src/main/resources/xml/toast.xml";
    public static void main(String[] args) {
        System.out.println("模块化-001");
        List<String> data = new ArrayList<>();
        data.add("TOAST-A");
        data.add("TOAST-B");
        data.add("TOAST-C");
        data.add("TOAST-D");
        StringListImpl strings = new StringListImpl(data);
        strings.forEach(System.out::println);
    }
}

        使用javac 命令将TestStringList 编译成 class文件;在编译时将java.xml 模块进行导出;结果如下图所示:

TestStringList.java:3: 警告: StringListImpl是内部专用 API, 可能会在未来发行版中删除
import com.sun.org.apache.xerces.internal.impl.xs.util.StringListImpl;

        由于我们的模块当中引用到了java.xml模块的代码,并且编译时也进行对应的导出;输出一条警告;该警告是由于java.xml这个模块已经不推荐使用了,日后项目中涉及到XML的业务也是推荐使用Java其他的第三方类库比这个要好;日后可能会被移除掉;

        这种警告并不会影响到程序的正常执行,毕竟程序员不管WARNING; 只管ERROR;

        程序执行程序,内容正常输入;

        其实本章的接口内容由于官方已经不推荐使用了,所以没有必要去深入了解;知道怎么去引入其他模块即可;当然如果是在JDK8的话,可以直接使用;

1.2 ArrayQueue

        这个ArrayQueue 是一个通过数组实现的单向队列;并且这个集合类也不属于java.base模块,是属于java.management 模块;该模块包含了一些用于管理和监控 java虚拟机和Java应用程序;

1.2.1 ArrayQueue 属性

    /** 队列的容量 */
    private int capacity;
    /** 队列 */
    private T[] queue;
    /** 一个指向队列头部的指针,即队列中第一个元素的索引位置 */
    private int head;
    /** 一个指向队列尾部的指针,即队列中最后一个元素的索引位置的下一个位置*/
    private int tail;

1.2.2  ArrayQueue的构造方法

    public ArrayQueue(int capacity) {
        this.capacity = capacity + 1;  // 队列容量大小
        this.queue = newArray(capacity + 1); // 根据容量创建列队
        this.head = 0; // 头部
        this.tail = 0; // 尾部
    }

    private T[] newArray(int size) {
        return (T[]) new Object[size];
    }

1.2.3 ArrayQueue 添加元素业务

    public boolean add(T o) {
        queue[tail] = o;  // 在当前尾部指针追加元素
        int newtail = (tail + 1) % capacity; // 新尾部元素加一
        /** 
         * 队列已满
         * 为什么要这样子判断;head 默认是0 ; newtail % capacity  假如 capacity 为 3
         * 1 % 3 = 1;
         * 2 % 3 = 2;
         * 3 % 3 = 0;  
         * 因为  % 3 等于 = 0 的永远都是3的倍数
         */
        if (newtail == head) 
            throw new IndexOutOfBoundsException("Queue full");
        tail = newtail;
        return true; // we did add something
    }

 1.2.4 ArrayQueue 删除元素业务

    /** 删除元素,该只支持从head开始删除 */
    public T remove(int i) {
        if (i != 0) // 如果i指针不等于0,则不是从head开始删除,不符合删除业务;
            throw new IllegalArgumentException("Can only remove head of queue");
        if (head == tail) // 头部和尾部指针都为0;说明队列为空
            throw new IndexOutOfBoundsException("Queue empty");
        T removed = queue[head]; // 要删除的元素
        queue[head] = null; // 要删除的位置设置为null
        head = (head + 1) % capacity; // head指针向前移动一位
        return removed; // 返回被删除的元素
    }

1.2.5 ArrayQueue 获取元素业务

    public T get(int i) {
        int size = size();// 获取当前队列大小
        if (i < 0 || i >= size) { // 判断索引是否越界
            final String msg = "Index " + i + ", queue size " + size;
            throw new IndexOutOfBoundsException(msg);
        }
        // 通过索引 + head 再 % capacity 可以找真正索引的的位置
        // 因为删除业务是从head开始删除,每删除一个,head都需要进行往前移动一位;所以 head + i 才是当前索引真正的位置
        int index = (head + i) % capacity; 
        return queue[index];
    }

    /** 获取队列容器大小 */
    public int size() {
        // Can't use % here because it's not mod: -3 % 2 is -1, not +1.
        int diff = tail - head;
        if (diff < 0)
            diff += capacity;
        return diff;
    }

1.2.6 ArrayQueue 扩容机制

    public void resize(int newcapacity) {
        int size = size(); // 获取当前大小
        if (newcapacity < size) // 指定扩容的容量 小于 当前大小;
            throw new IndexOutOfBoundsException("Resizing would lose data");
        newcapacity++;
        // 指定扩容的容量 等于现在的容量
        if (newcapacity == this.capacity) return;
        // 指定扩容的容量获取一个新数组;然后通过for将旧数组的数据一个一个复制到里面
        T[] newqueue = newArray(newcapacity);
        for (int i = 0; i < size; i++)
            newqueue[i] = get(i);
        this.capacity = newcapacity;
        this.queue = newqueue;
        this.head = 0;
        this.tail = size;
    }

         ArrayQueue 源码其实非常简单;功能也很简单;读起来并不难!

  • 19
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值