//===========================测试代码============================
public class Main {
public static void main(String[] args) {
MyStack<String> oldStack = new MyStack<>();
MyStack<String> newStack = new MyStack<>();
oldStack.push("百度");
oldStack.push("淘宝");
oldStack.push("腾讯");
MyStack<String> click = new MyStack<>();
click.back(oldStack, newStack);//退到淘宝
click.back(oldStack, newStack);//退到百度
click.insertNewPage("拼多多", oldStack, newStack);
System.out.println(oldStack.list.toString());
click.back(oldStack, newStack);//退到百度
click.go(oldStack, newStack);//拼多多
System.out.println(oldStack.list.toString());
}
}
//===============================stack================================
package com.fine.stack;
import com.fine.List;
import com.fine.list.MyArrayList;
/**
* @description: 后进先出
* @author:
* 接口设计: size 入栈 出栈 清空 获取栈顶元素 是否为空
*/
public class MyStack<E> {
public List<E> list = new MyArrayList();
/**
* 入栈
*
* @param element
*/
public void push(E element) {
list.add(element);
}
/**
* 出栈
*
* @return
*/
public E pop() {
//删除栈顶元素
return list.remove(list.size() - 1);
}
/**
* 获取栈顶元素
*/
public E getTop() {
return list.get(list.size() - 1);
}
/**
* 模拟浏览器页面前进、后退、进入新页面
*/
public void go(MyStack<E> oldStack, MyStack<E> newStack) {
if (newStack.list.size() > 0) {
E pop = newStack.pop();
oldStack.push(pop);
System.out.println("前进到" + oldStack.getTop().toString());
} else {
System.out.println("已经最前面了");
}
}
public void back(MyStack<E> oldStack, MyStack<E> newStack) {
if (oldStack.list.size() > 0) {
E pop = oldStack.pop();
newStack.push(pop);
System.out.println("回退到" + oldStack.getTop().toString());
} else {
System.out.println("已经最后一页了");
}
}
public void insertNewPage(E element, MyStack<E> oldStack, MyStack<E> newStack) {
oldStack.push(element);
newStack = new MyStack<>();
}
}
//=======================MyArrayList==========================
package com.fine.list;
import com.fine.AbstractList;
@SuppressWarnings("unchecked")
public class MyArrayList<E> extends AbstractList<E> {
/**
* 所有的元素
*/
private E[] elements;
public MyArrayList() {
this(DEFAULT_CAPACITY);
}
public MyArrayList(int capacity) {
if (capacity > 0) {
elements = (E[]) new Object[capacity];
} else {
/**
*1.a:创建一定容量的新数组,内存会分配连续的字节(内存地址),如果数组是int类型,则一共分配了4*10个字节
* b:移除元素时,由于内存地址是连续的,所以不能把要移除地方全部删掉,内存不支持这种操作,只有元素往前挪
*2.a:针对应用类型,创建数组在堆开辟内存空间,每一个元素真正的数据再重新开辟空间,数组上存的是元素的内存地址值,不是直接存对应上元素,
* 如果数组直接存对象,该位置的对象大小是动态的,所以直接存地址更好,也更节省空间,比如数组默认长度10,一个对象10个字节,就需要100个字节,但如果存地址就无需开辟这么多
* b:针对基本类型,数组上直接存值
*3.a:内存空间如何销毁
* 直接清除数组上的內存地址
*
*/
elements = (E[]) new Object[DEFAULT_CAPACITY];
}
}
/**
* 清除所有元素
*/
public void clear() {
for (int index = 0; index < size; index++) {
elements[index] = null;
}
size = 0;
}
/**
* 是否包含某个元素
*
* @param element
* @return
*/
public boolean contains(E element) {
boolean result = false;
for (int index = 0; index < size; index++) {
if (elements[index].equals(element)) {
result = true;
}
}
return result;
}
/**
* 添加元素到尾部
*
* @param element
*/
public void add(E element) {
if (size < elements.length) {
this.addIndex(size, element);
} else {
//扩容再添加
this.ensureCapacity(size + 1);
this.addIndex(size, element);
}
}
/**
* 在index位置插入一个元素
* 在指定位置插入,后面位置的元素向后挪动,如果超出了索引范围就追加在最后面,索引小于0加在最前面
*
* @param index
* @param element
*/
public void addIndex(int index, E element) {
this.rangeCheckForAdd(index);
if (index < 0) {
index = 0;
}
for (int i = size - 1; i >= index; i--) {
if (i + 1 <= elements.length - 1) {
elements[i + 1] = elements[i];
} else {
this.ensureCapacity(size + 1);
elements[i + 1] = elements[i];
}
}
if (index >= elements.length) {
this.ensureCapacity(size + 1);
}
elements[index] = element;
++size;
}
/**
* 获取index位置的元素,访问时间和下标没有关系
* 不管取索引是多少的元素复杂度都是O(1),因为底层是直接解析nums[index]算出地址,通过地址去找元素
*
* @param index
* @return
*/
public E get(int index) {
this.rangeCheck(index);
return elements[index];
}
/**
* 设置index位置的元素
*
* @param index
* @param element
* @return 原来的元素ֵ
*/
public E set(int index, E element) {
this.rangeCheck(index);
E old = elements[index];
elements[index] = element;
return old;
}
/**
* 删除index位置的元素
* 删除一个元素其实是改为元素的后一个元素向前覆盖
*
* @param index
* @return 成功移除的元素, 失败抛异常
*/
public E remove(int index) {
this.rangeCheck(index);
E oldEle = elements[index];
//移动元素
for (int i = index; i < size - 1; i++) {
elements[i] = elements[i + 1];
}
//最后一个元素
elements[--size] = null;
if (elements.length >> 2 >= size && elements.length > DEFAULT_CAPACITY) {
tirm();
} else {
return oldEle;
}
return oldEle;
}
/**
* 缩容
*/
private void tirm() {
int oldCapacity = elements.length;
int newCapacity = oldCapacity >> 1;
E[] newElements = (E[]) new Object[newCapacity];
for (int index = 0; index < size; index++) {
newElements[index] = elements[index];
}
elements = newElements;
System.out.println(oldCapacity + "缩容为" + newCapacity);
}
/**
* 查看元素的索引
*
* @param element
* @return
*/
public int indexOf(E element) {
if (element == null) {
for (int index = 0; index < size; index++) {
if (elements[index] == null) return index;
}
} else {
for (int index = 0; index < size; index++) {
if (elements[index].equals(element)) return index;
}
}
return ELEMENT_NOT_FOUND;
}
/**
* 保证要有capacity的容量
* 不允许在老数组后面申请新的内存空间,只有重新开辟一块新空间,把老数据加进去
*
* @param capacity
*/
private void ensureCapacity(int capacity) {
int oldCapacity = elements.length;
if (oldCapacity >= capacity) {
return;
}
//浮点数的计算比整数计算更耗时间,所以这里不用浮点数计算
//double newCapacityDoub = oldCapacity * 1.5; >>1 = /2 ;<<1 = *2
int newCapacity = oldCapacity + (oldCapacity >> 1);
E[] newElements = (E[]) new Object[newCapacity];
for (int index = 0; index < size; index++) {
newElements[index] = elements[index];
}
elements = newElements;
System.out.println(oldCapacity + "扩容为" + newCapacity);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("size=" + size + ":[");
if (size == 0) {
sb.append("]");
} else {
for (int i = 0; i < size; i++) {
if (i == (size - 1)) {
sb.append(elements[i] + "]");
} else {
sb.append(elements[i] + ",");
}
}
}
return new String(sb);
}
}
//=============================AbstractList================================
package com.fine;
/**
* 抽象类可以不实现接口的方法
* 此类不对外公开,负责封装公共方法
* @param <E>
*/
public abstract class AbstractList<E> implements List<E> {
/**
* 元素的数量
*/
protected int size;
/**
* 元素的数量
*
* @return
*/
public int size() {
return size;
}
/**
* 是否为空
*
* @return
*/
public boolean isEmpty() {
return size == 0;
}
public void outOfBounds(int index) {
throw new IndexOutOfBoundsException("index=" + index + ",size=" + size);
}
public void rangeCheck(int index) {
if (index < 0 || index >= size) {
this.outOfBounds(index);
}
}
public void rangeCheckForAdd(int index) {
if (index < 0 || index > size) {
this.outOfBounds(index);
}
}
}
//============================List接口==============================
package com.fine;
public interface List<E> {
public static final int DEFAULT_CAPACITY = 2;
public static final int ELEMENT_NOT_FOUND = -1;
/**
* 清除所有元素
*/
public void clear();
/**
* 是否包含某个元素
*
* @param element
* @return
*/
public boolean contains(E element);
/**
* 添加元素到尾部
*
* @param element
*/
public void add(E element);
/**
* 在index位置插入一个元素
* @param index
* @param element
*/
public void addIndex(int index, E element);
/**
* 获取index位置的元素
*
* @param index
* @return
*/
public E get(int index);
/**
* 设置index位置的元素
*
* @param index
* @param element
* @return 原来的元素ֵ
*/
public E set(int index, E element);
/**
* 删除index位置的元素
* @param index
* @return 成功移除的元素, 失败抛异常
*/
public E remove(int index);
/**
* 查看元素的索引
*
* @param element
* @return
*/
public int indexOf(E element);
/**
* 元素的数量
*
* @return
*/
public int size();
}