实现一个数据结构:栈,支持泛型,考虑扩容,加入线程同步
之前刷过不少又偏又难的算法题,忽然感觉有点跑偏了,貌似校招中大前端(web前端、移动客户端)的笔试和面试题,并没有逻辑上特别难的,普遍偏向于数据结构与工程化代码规范的考察。
就像这题看起来逻辑上确实不怎么难,栈嘛,会编程的基本上都用过,也知道它就是个『后进先出』的数据结构。但是在视频面试中,面试官就守在电脑前,看着你一个字符一个字符的在非IDE环境下敲出的代码,在这种情况下我写出的代码问题还是很多的。先上正确的代码:
public class Stack<E> {
private static final int INIT_SIZE = 2; // 栈的默认初始大小
private Object[] stack; // Java不支持泛型数组,可使用Java提供的容器,但本题并不允许使用Java提供的容器类
private int index; // 栈顶索引
/**
* 构造方法,未指定栈的初始大小,使用默认大小
*/
public Stack() {
stack = new Object[INIT_SIZE];
index = -1;
}
/**
* 构造方法,指定栈的初始大小
*
* @param initSize
*/
public Stack(int initSize) {
if (initSize < 0) {
throw new IllegalArgumentException();
}
stack = new Object[initSize];
index = -1;
}
/**
* 出栈操作
*
* @return 栈顶对象
*/
public synchronized E pop() {
if (!isEmpty()) {
E top = (E) stack[index];
stack[index--] = null; // 将要弹出的元素置空,避免内存泄露
return top;
}
return null;
}
/**
* 入栈操作
*
* @param obj 等待入栈的对象
*/
public synchronized void push(E obj) {
if (isFull()) {
Object[] src = stack;
stack = new Object[2 * stack.length]; // 如果栈满,则创建空间为当前栈空间两倍的栈
System.arraycopy(src, 0, stack, 0, src.length);
}
stack[++index] = obj;
}
/**
* 查看栈顶对象
*
* @return 栈顶对象
*/
public E peek() {
if (!isEmpty()) {
return (E) stack[index];
}
return null;
}
/**
* 查看栈是否为空
*
* @return 如果栈为空返回true,否则返回false
*/
public boolean isEmpty() {
return index == -1;
}
/**
* 查看栈是否满
*
* @return 如果栈满返回true, 否则返回false
*/
public boolean isFull() {
return index >= stack.length - 1;
}
}
我面试时写的代码就不上了,写的太挫,总结前来主要问题如下:
- 莫名其妙的给构造方法加了个void返回值
- 竟然写了出了
private E[] stack;
这样的代码,然后被面试官问到是否了解Java泛型机制,我回答了『编译时检查,然后擦除』,然后面试官反问到,那你这个E类型的数组能new出来吗?尴尬~ - 将泛型类和泛型方法弄混,本题实现的是一个泛型类Stack<E>,类中的方法没必要再写成泛型方法。
- 没有将要弹出的元素置空,导致内存泄露。
- synchronized拼写错误,囧