一,简介
如上图所示,前面的章节一和章节二主要是将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 源码其实非常简单;功能也很简单;读起来并不难!