不可变队列ImmuableQueue<E>

1.理解不可变性,对象一旦生成,内部状态不会发生变化,所以是线程安全的;

2.实现不可变队列ImmutableQueue<E>,利用两个不可变栈ImmutableStack<E>实现。

(一)不可变栈ImmutableStack<E>实现

import java.util.Collections;
import java.util.NoSuchElementException;

/**
 * @author pizi
 * The Stack class represents an immutable first-in-last-out(FILO) stack of objects.
 * @param <E>
 * 
 */
public final class ImmutableStack<E> {
    
	public final static ImmutableStack EMPTY_STACK = new ImmutableStack<>();
	
	private final E front;
	private final ImmutableStack<E> tail;
	private final int size;
	
	
	public ImmutableStack() {
		front = null;
		tail = null;
		size = 0;
	}
	
	// not safe
	public static  final <E> ImmutableStack<E> emptyStack() {
		return (ImmutableStack<E>)EMPTY_STACK;
	}
	
	private ImmutableStack(E f, ImmutableStack<E> t) {
		front = f;
		tail = t;
		size = tail.size() + 1;
	}
	
	/**
	  * 
	  * <pre>
	  * e.g.
	  * When this stack represents the stack(7, 1, 3, 3, 5, 1),
	  * this method returns 1 and this object still represents the stack(7, 1, 3, 3, 5, 1)
	  * </pre>
	  * If the stack is empty, throws java.util.NoSuchElementException.
	  * @return
	  * @throws java.util.NoSuchElementException
	  */
	 public E peek() {
		if (isEmpty()) {
			throw new NoSuchElementException();
		}
		return front;
	}
	
	/**
	 * Returns the stack that adds an item into the front of this stack without modifying this stack.
	 * <pre>
	 * e.g.
	 * When this stack represents the stack (2, 1, 2, 2, 6) and we push the value 4 into this stack,
	 * this method returns a new stack(2, 1, 2, 2, 6, 4)
	 * and this object still represents the stack(2, 1, 2, 2, 6).
	 * </pre>
	 * If the element e is null, throws IllegalArgumentException.
	 * @param e
	 * @return
	 * @throws IllegalArgumentException
	 */
	public ImmutableStack<E> push(E e) {
		if (e == null) {
			throw new IllegalArgumentException();
		}
		return new ImmutableStack<E>(e, this);
		
	}
	
	/**
	  * Returns the stack that removes the object at the front of this stack without modifying this stack.
	  * <pre>
	  * e.g.
	  * When this stack represents the stack(7, 1, 3, 3, 5, 1),
	  * this method returns a new stack(7, 1, 3, 3, 5)
	  * and this object still represents the stack(7, 1, 3, 3, 5, 1).
	  * </pre>
	  * If this stack is empty, throws java.util.NoSuchElementException.
	  * @return
	  * @throws java.util.NoSuchElementException
	  */
	public ImmutableStack<E> pop() {
		if (isEmpty()) {
			throw new NoSuchElementException();
		}
		return tail;
	}
	
	/**
	 * reverse the stack elements to a new stack
	 */
	public ImmutableStack<E> reverse() {
		if (isEmpty()) {
			return new ImmutableStack<E>();
		}
		ImmutableStack<E> newStack = emptyStack();
		//ImmutableStack<E> newStack = new ImmutableStack<E>();
		ImmutableStack<E> currentStack = this;
		while (!currentStack.isEmpty()) {
			newStack = newStack.push(currentStack.peek());
			currentStack = currentStack.pop();
		}
		/**
		 * ImmutableStack<E> r = emptyStack();
		 * for (ImmutableStack<E> f = this; !f.isEmpty(); f = f.pop()) {
		 *    r = r.push(f.peek());
		 * }
		 */
		return newStack;
		
	}
	
	 /**
	   * Returns the number of objects in this stack.
	   * @return
	   */
	public int size() {
		return size;
	}
	
	/**
     * <p>This implementation returns <tt>size() == 0</tt>.
     */
	public boolean isEmpty() {
		return size() == 0;
	}
	
	public String toString() {
		  if (isEmpty()) {
			  return "[]";
		  }
		  
	      ImmutableStack<E> currentStack = this.reverse();
	      StringBuffer sb = new StringBuffer();
	      sb.append("[");
	      while (!currentStack.isEmpty()) {
	    	  sb.append(currentStack.peek() + (currentStack.size() > 1 ? ", " : ""));
	    	  currentStack = currentStack.pop();
	      }
	      return sb.append("]").toString();
	}
}
(二)不可变队列ImmutableQueue<E>实现

import java.util.Collections;
import java.util.NoSuchElementException;
/**
 * @author pizi
 * The Queue class represents an immutable first-in-first-out(FIFO) queue of objects.
 * @param <E>
 * 
 */
public final class ImmutableQueue<E> {
   
	
	private final ImmutableStack<E> enterStack;
	private final ImmutableStack<E> outStack;
	
	public static final ImmutableQueue EMPTY_QUEUE = new ImmutableQueue<>();
	
	/**
    * requires default constructor
    */
	public ImmutableQueue() {
		// modify this constructor if necessary,but do not remove default constructor
		enterStack = ImmutableStack.EMPTY_STACK;
		outStack = ImmutableStack.EMPTY_STACK;
	}
	// add other constructors if necessary
	private ImmutableQueue(ImmutableStack<E> eStack, ImmutableStack<E> oStack) {
		
		enterStack = eStack;
		outStack = oStack;
		
	}
	
	/**
	 * @SuppressWarnings("unchecked")
	 */
	public static final <E> ImmutableQueue<E> emptyQueue() {
		
		return (ImmutableQueue<E>)EMPTY_QUEUE;
	}
	
	/*private static <E> E cast(Object o) {
		return (E)o;
	}*/
	/**
	 * Returns the queue that adds an item into the tail of this queue without modifying this queue.
	 * <pre>
	 * e.g.
	 * When this queue represents the queue (2, 1, 2, 2 6) and we enqueue the value 4 into this queue,
	 * this method returns a new queue(2, 1, 2, 2, 6, 4)
	 * and this object still represents the queue(2, 1, 2, 2, 6).
	 * </pre>
	 * If the element e is null, throws IllegalArgumentException.
	 * @param e
	 * @return
	 * @throws IllegalArgumentException
	 */
	 public ImmutableQueue<E> enqueue(E e) {
		 if (e == null) {
			 throw new IllegalArgumentException();
		 }
		 return new ImmutableQueue<E>(enterStack.push(e), outStack);
		 
	 }
	 
	 /**
	  * Returns the queue that removes the object at the head of this queue without modifying this queue.
	  * <pre>
	  * e.g.
	  * When this queue represents the queue(7, 1, 3, 3, 5, 1),
	  * this method returns a new queue(1, 3, 3, 5, 1)
	  * and this object still represents the queue(7, 1, 3, 3, 5, 1).
	  * </pre>
	  * If this queue is empty, throws java.util.NoSuchElementException.
	  * @return
	  * @throws java.util.NoSuchElementException
	  */
	 public ImmutableQueue<E> dequeue() {
		 
		 if (isEmpty()) {
			 throw new NoSuchElementException();
		 }
		 if (size() == 1) {
			 return emptyQueue();
			 //return new ImmutableQueue<E>();
		 }
		 // queue is not empty but outStack is empty and enterStack is not empty
		 if (outStack.isEmpty()) {
			 ImmutableStack<E> stack = enterStack.reverse();
			 return new ImmutableQueue<E>(ImmutableStack.EMPTY_STACK,stack.pop());
			 //return new ImmutableQueue<E>(new ImmutableStack<E>(), stack.pop());
		 }
		 // queue is not empty and outStack is not empty and enterStack may be empty or not
		return new ImmutableQueue<E>(enterStack, outStack.pop());
		
	 }
	 
	 /**
	  * Looks at the object which is the head of this queue without removing it from the queue.
	  * <pre>
	  * e.g.
	  * When this queue represents the queue(7, 1, 3, 3, 5, 1),
	  * this method returns 7 and this object still represents the queue(7, 1, 3, 3, 5, 1)
	  * </pre>
	  * If the queue is empty, throws java.util.NoSuchElementException.
	  * @return
	  * @throws java.util.NoSuchElementException
	  */
	  public E peek() {
		  
		  if (isEmpty()) {
			  throw new NoSuchElementException();
		  }
		  // queue is not empty but outStack is empty and enterStack is not empty
		  if (outStack.isEmpty()) {
			  ImmutableStack<E> stack = enterStack.reverse();
			  return stack.peek();
		  }
		  // outStack is not empty
		  return outStack.peek();
		 
	  }
	  
	  /**
	   * Returns the number of objects in this queue.
	   * @return
	   */
	   public int size() {
		   
		  return enterStack.size() + outStack.size();
	   }
	   
	   /**
	    * 
	    */
	   public boolean isEmpty() {
		   
		   return enterStack.isEmpty() && 
				  outStack.isEmpty();
	   }
	   
	   public String toString() {
		   
		   if (isEmpty()) {
			   return "[]";
		   }
		   StringBuffer sb = new StringBuffer();
		   sb.append("[");
		   // outStack is empty and enterStack is not empty
		   if (outStack.isEmpty() && !enterStack.isEmpty()) {
			   sb = toQueueString(sb, enterStack.reverse());
		   }
		   // outStack is not empty and enterStack is empty
		   if (!outStack.isEmpty() && enterStack.isEmpty()){
			   sb = toQueueString(sb, outStack);			   
		   }
		   // outStack is not empty and enterStack is not empty
		   if (!outStack.isEmpty() && !enterStack.isEmpty()) {
			   sb = toQueueString(sb, outStack);
			   sb.append(", ");
			   sb = toQueueString(sb, enterStack.reverse());			   
		   }
		   return sb.append("]").toString();
	   }
	   
	   private StringBuffer toQueueString(StringBuffer sb, ImmutableStack<E> stack) {
		   
		   while (!stack.isEmpty()) {
			   sb.append(stack.peek() + (stack.size() > 1 ? ", " : ""));
			   stack = stack.pop();
		   }
		   return sb;
	   } 
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值