1.在IndexBox接口中定义规则 使用泛型讲不确定的数据类型定义成<E>
package com.buka;
public interface IndexBox<E> extends Box<E> {
/**
* 得到指定位置的数据
* @param i 指定的位置
* @return 得到的数据
*/
E get(int i);
/**
* 将数据放到指定的位置
* @param e 存放的数据
* @param i 要存放的位置
* @return 为true表示存储成功,为false表示存储失败
*/
boolean add(E e, int i);
/**
* 将一组数据放到指定的位置
* @param es 要存放的一组数据
* @param i 要存放的位置
* @return 为true表示存储成功,为false表示存储失败
*/
boolean add(E[] es, int i);
/**
* 将另一个容器里的数据放到当前容器的指定的位置
* @param box 要存放的另一个容器
* @param i 要存放的位置
* @return 为true表示存储成功,为false表示存储失败
*/
boolean add(Box<? extends E> box, int i);
/**
* 删除指定位置的数据
* @param i 要删除的位置
* @return 删除的数据
*/
E remove(int i);
}
对于IndexBox的规则定义需要新创建Manager接口用于辅助实现
package com.buka;
public interface Manager<E> {
/**
* 判断是否还有下一个数据
* @return true表示有下一个数据,false表示没有
*/
boolean hasNext();
/**
* 得到当前指针只向的数据,并向下移动指针
* @return 得到的数据
*/
E getNext();
/**
* 判断是否还有上一个数据
* @return true表示有上一个数据,false表示没有
*/
boolean hasPrev();
/**
* 得到当前指针只向的数据,并向上移动指针
* @return 得到的数据
*/
E getPrev();
/**
* 得到box中存储的第一个数据
* @return 得到的数据
*/
E getFirst();
/**
* 得到box中存储的最后一个数据
* @return 得到的数据
*/
E getLast();
/**
* 重写开始记录指针在box中的位置
*/
void reStart();
}
2.将定义好的规则打包 导入新的项目 在新的项目中对规则进行重写
创建LinkedBox 继承IndexBox
生成重写方法 并进行重写
package com.buka;
public class LinkedBox<E> implements IndexBox<E> {
class Node<T> {
//节点中的数据
T element;
//节点中上一个节点的地址
Node<T> prev;
//节点中下一个节点的地址
Node<T> next;
public Node() {
}
public Node(T element, Node<T> next, Node<T> prev) {
this.element = element;
this.next = next;
this.prev = prev;
}
}
//记录头节点,就可以得到整个链表
private Node<E> first;
//记录尾节点,也可以得到整个链表
private Node<E> last;
//记录存储元素的数量(节点的数量)
private int size = 0;
private void checkIndex(int i){
if(i <0|| i>=size){
throw new BoxIndexOutOfBoundsException("Size:"+size+",Index:"+i);
}
}
@Override
public E get(int i) {
checkIndex(i);
return find(i).element;
}
private Node<E> find(int i) {
//i = 0;
int count = 0;
Node<E> curr = first;
while (count < i) {
curr = curr.next;
count++;
}
return curr;
}
@Override
public boolean add(E e, int i) {
if (i < 0 || i > size) {
throw new BoxIndexOutOfBoundsException("Size" + size + ",Index" + i);
}
Node<E> n = find(i);
if (n == null) {
add(e);
return true;
}
Node<E> newNode = new Node<E>();
newNode.element = e;
if (n.prev == null) {
//n就是first
newNode.next = n;
n.prev = newNode;
first = newNode;
size++;
return true;
}
n.prev.next = newNode;
n.prev = newNode;
newNode.prev = n.prev;
newNode.next = n;
size++;
return true;
}
@Override
public boolean add(E[] es, int i) {
for (E e : es) {
add(e, i++);
}
return true;
}
@Override
public boolean add(Box<? extends E> box, int i) {
Manager<? extends E> manager = box.getManager();
while (manager.hasNext()) {
E next =manager.getNext();
add(next,i++);
}
return true;
}
@Override
public E remove(int i) {
checkIndex(i);
Node<E> n = find(i);
if(n.next == null){
//n是最后一个
last = n.prev ;
n.prev.next = null ;
n.prev = null ;
}else if(n.prev == null){
//n是第一个节点
first = n.next ;
n.next.prev = null ;
n.next = null ;
}else{
//n是中间的节点
Node<E> prev = n.prev ;
Node<E> next = n.next ;
n.prev = null ;
n.next = null ;
prev.next = next ;
next.prev = prev ;
}
size -- ;
return n.element;
}
@Override
public boolean add(E e) {
//添加元素,对于链表结构而言,每一个元素在链表中都是以节点的形式存储
Node<E> newNode = new Node<E>();
newNode.element = e;
if (first == null) {
//链表中一个节点都没有
//当前这个节点,又是头节点,又尾节点
first = newNode;
last = newNode;
} else {
//链表中本身就有一些节点
//此时新节点应该放在之前那个last节点的后面
//放完之后,当前这个新节点就变成了last节点
last.next = newNode; //null.xxx last = null
newNode.prev = last;
last = newNode;
}
size++;
return true;
}
@Override
public boolean add(E[] es) {
for (int i = 0; i < es.length; i++) {
add(es[i]);
}
return true;
}
@Override
public boolean add(Box<? extends E> box) {
Manager<? extends E> manager = box.getManager();
while (manager.hasNext()) {
E e = manager.getNext();
add(e);
}
return true;
}
@Override
public Manager<E> getManager() {
return new LinkedManager<E>();
}
private class LinkedManager<E> implements Manager<E>{
private Node<E> curr = (Node<E>) first;
private Node<E> curr2 = (Node<E>) last;
@Override
public boolean hasNext() {
return curr != null ;
}
@Override
public E getNext() {
try {
return curr.element;
}finally {
curr = curr.next ;
}
}
@Override
public boolean hasPrev() {
return curr2 != null;
}
@Override
public E getPrev() {
try{
return curr2.element;
}finally {
curr2 =curr2.prev ;
}
}
@Override
public E getFirst() {
return (E) first.element;
}
@Override
public E getLast() {
return (E) last.element;
}
@Override
public void reStart() {
curr = (Node<E>) first;
}
}
@Override
public int size() {
return size;
}
@Override
public void show() {
//打印存储的所有元素
//所有的元素都在节点中存储
//怎么能得到所有的节点呢?
//可以从头结点,一个一个的往后找。也可以从尾节点一个一个的往前找
Node<E> curr = first;
while (curr != null) {
E e = curr.element;
System.out.println(e);
curr = curr.next;
}
}
}
3.在重写过程中我新定义了一个异常 用于处理IndexBox出现不合理数据或不合法范围。
package com.buka;
public class BoxIndexOutOfBoundsException extends RuntimeException{
BoxIndexOutOfBoundsException(){}
BoxIndexOutOfBoundsException(String msg){
super(msg);
}
}
4.最后对于我进行的链式封装进行测试
public static void main(String[] args) {
LinkedBox<String> box = new LinkedBox<>();
box.add("car1");
box.add("car2");
box.add("car3");
box.show();
System.out.println("---------------------------");
Manager<String> manager = box.getManager();
while (manager.hasNext()) {
String next = manager.getNext();
System.out.println(next.toUpperCase());
}
System.out.println("---------------------------");
LinkedBox<String> box2 = new LinkedBox<String>();
box2.add("car4");
box2.add("car5");
box2.add("car5");
box.add(box2);
box.show();
System.out.println("---------------------------");
IndexBox box1 = box;
box1.add("car6",1);
box1.show();
System.out.println("---------------------------");
box1.remove(2);
box1.show();
}
5.对此我们完成了链式封装
在进行完善的时候我遇到了 算法逻辑 等问题并积极学习改进