`

java 实现undo和redo操作链表的一种实现

    博客分类:
  • java
阅读更多
今天在iteye论坛逛,发现有这么一道笔试题目:实现一个可以增加一个节点、删除某个区间的节点、修改某个节点、undo和redo的链表。
有个网友atomduan给这道题目的一种实现形式,现在我在他的代码上加了注释,利于理解。

import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;

public class EditableLinkedList<T> {
	
	private LinkedList<T> primaryList = new LinkedList<T>();
	
	//快照列表
	private LinkedList<List> snapshotList = new LinkedList<List>();
	
	//上一次操作调用的方法
	private Method lastOperation;
	
	//上一次操作调用的方法参数
	private Object[] lastOperationArgs;
	
	//拍快照,每操作一次拍下快照
	private void takeSnapshot() {
		List<T> snapshot = new LinkedList<T>();
		for (T element : primaryList) {
			snapshot.add(element);
		}
		snapshotList.add(snapshot);
	}
	
	//从最新的快照恢复
	private void restoreFromSnapshot() {
		//pollLast()获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
		List<T> snapshot = snapshotList.pollLast();  
		primaryList.clear();
		for (T element : snapshot) {
			primaryList.add(element);
		}
	}
	
	//设置上次操作
	private void setLastInvokedOperation(String methodName, Object... params) {
		try {
			this.lastOperation = this.getClass().
				getMethod(methodName, this.getParamTypes(params));
		} catch (Exception e) {
			if (setLastMethodParamsGeneric(methodName, params)==false){
				e.printStackTrace();
			}
		}
		this.lastOperationArgs = params;
	}
     
	//设置上一个方法的参数
	private boolean setLastMethodParamsGeneric(String methodName, Object... params) {
		Method[] methods = this.getClass().getMethods();
		for (int i=0; i<methods.length; i++) {
			if (this.isMethodMatch(methods[i], methodName, params)) {
				this.lastOperation = methods[i];
				return true;
			}
		}
		return false;
	}
	
	//判断方法是否匹配
	private boolean isMethodMatch(Method method, String methodName, Object... params){
		if (!method.getName().equalsIgnoreCase(methodName)) {
			return false;
		}
		Class<?>[] paramTypes = method.getParameterTypes();
		if (paramTypes.length != params.length) {
			return false;
		}
		for (int i=0; i<params.length; i++) {
			if (!paramTypes[i].isAssignableFrom(params[i].getClass())) {
				return false;
			}
		}
		return true;
	}
	
	//获取参数的类型
	private Class<?>[] getParamTypes(Object... params) {
		Class<?>[] paramTypes = new Class<?>[params.length];
		for (int i=0; i<params.length; i++) {
			paramTypes[i] = params[i].getClass(); 
		}
		return paramTypes;
	}
	
	//执行上一个方法
	private void invokeLastMethod() {
		try {
			this.lastOperation.invoke(this, this.lastOperationArgs);
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	//删除操作
	public void delete(Integer beginIndex, Integer endIndex) {
		//删除操作之前拍下快照
		this.takeSnapshot();
		for (int i=beginIndex; i<=endIndex; i++) {
			primaryList.remove(beginIndex);
		}
		this.setLastInvokedOperation("delete", beginIndex, endIndex);
	}
	
	//插入操作
	public void insert(T element, Integer index) {
		//插入操作之前拍下快照
		this.takeSnapshot();
		primaryList.add(index, element);
		this.setLastInvokedOperation("insert", element, index);
	}
	
	//修改操作
	public void modify(T element, Integer index) {
		//修改操作之前拍下快照
		this.takeSnapshot();
		primaryList.set(index, element);
		this.setLastInvokedOperation("modify", element, index);
	}
	
	//重做,取消复原
	public void redo() {
		//执行上次操作的方法
		this.invokeLastMethod();
	}
	
    //撤销
	public void undo() {
		//重最新的快照中恢复
		this.restoreFromSnapshot();
	}
	
	public String toString() {
		return this.primaryList.toString();
	}
	
	public static void main(String[] args) {
		EditableLinkedList<String> ell = new EditableLinkedList<String>();
		ell.insert("hey", 0);
		System.out.println(ell);
		ell.redo();
		System.out.println(ell);
		ell.undo();
		System.out.println(ell);
		ell.redo();
		System.out.println(ell);
		ell.undo();
		System.out.println(ell);
		ell.undo();
		System.out.println(ell);
	}
}

运行结果:
[hey]
[hey, hey]
[hey]
[hey, hey]
[hey]
[]
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics