@@ -259,6 +259,105 @@ public class TupleTest {
259259
260260在上面的程序中,` new ` 表达式有些啰嗦。本章稍后会介绍,如何利用 * 泛型方法* 简化它们。
261261
262+ ### 一个堆栈类
263+
264+ 接下来我们看一个稍微复杂一点的例子:堆栈。在[ 集合] ( ./12-Collections.md ) 一章中,我们用 ` LinkedList ` 实现了 ` onjava.Stack ` 类。在那个例子中,` LinkedList ` 本身已经具备了创建堆栈所需的方法。` Stack ` 是通过两个泛型类 ` Stack<T> ` 和 ` LinkedList<T> ` 的组合来创建。我们可以看出,泛型只不过是一种类型罢了(稍后我们会看到一些例外的情况)。
265+
266+ 这次我们不用 ` LinkedList ` 来实现自己的内部链式存储机制。
267+
268+ ``` java
269+ // generics/LinkedStack.java
270+ // 用链式结构实现的堆栈
271+
272+ public class LinkedStack <T> {
273+ private static class Node <U> {
274+ U item;
275+ Node<U > next;
276+
277+ Node () { item = null ; next = null ; }
278+ Node (U item , Node<U > next ) {
279+ this . item = item;
280+ this . next = next;
281+ }
282+
283+ boolean end () {
284+ return item == null && next == null ;
285+ }
286+ }
287+
288+ private Node<T > top = new Node<> (); // 栈顶
289+
290+ public void push (T item ) {
291+ top = new Node<> (item, top);
292+ }
293+
294+ public T pop () {
295+ T result = top. item;
296+ if (! top. end()) {
297+ top = top. next;
298+ }
299+ return result;
300+ }
301+
302+ public static void main (String [] args ) {
303+ LinkedStack<String > lss = new LinkedStack<> ();
304+ for (String s : " Phasers on stun!" . split(" " )) {
305+ lss. push(s);
306+ }
307+ String s;
308+ while ((s = lss. pop()) != null ) {
309+ System . out. println(s);
310+ }
311+ }
312+ }
313+ ```
314+
315+ 输出结果:
316+
317+ ``` java
318+ stun!
319+ on
320+ Phasers
321+ ```
322+
323+ 内部类 ` Node ` 也是一个泛型,它拥有自己的类型参数。
324+
325+ 这个例子使用了一个 * 末端标识* (end sentinel) 来判断栈何时为空。这个末端标识是在构造 ` LinkedStack ` 时创建的。然后,每次调用 ` push() ` 就会创建一个 ` Node<T> ` 对象,并将其链接到前一个 ` Node<T> ` 对象。当你调用 ` pop() ` 方法时,总是返回 ` top.item ` ,然后丢弃当前 ` top ` 所指向的 ` Node<T> ` ,并将 ` top ` 指向下一个 ` Node<T> ` ,除非到达末端标识,这时就不能再移动 ` top ` 了。如果已经到达末端,程序还继续调用 ` pop() ` 方法,它只能得到 ` null ` ,说明栈已经空了。
326+
327+ ### RandomList
328+
329+ 作为容器的另一个例子,假设我们需要一个持有特定类型对象的列表,每次调用它的 ` select() ` 方法时都随机返回一个元素。如果希望这种列表可以适用于各种类型,就需要使用泛型:
330+
331+ ``` java
332+ // generics/RandomList.java
333+ import java.util.* ;
334+ import java.util.stream.* ;
335+
336+ public class RandomList <T> extends ArrayList<T > {
337+ private Random rand = new Random (47 );
338+
339+ public T select () {
340+ return get(rand. nextInt(size()));
341+ }
342+
343+ public static void main (String [] args ) {
344+ RandomList<String > rs = new RandomList<> ();
345+ Array . stream(" The quick brown fox jumped over the lazy brown dog" . split(" " )). forEach(rs:: add);
346+ IntStream . range(0 , 11 ). forEach(i - >
347+ System . out. print(rs. select() + " " ));
348+ );
349+ }
350+ }
351+ ```
352+
353+ 输出结果:
354+
355+ ``` java
356+ brown over fox quick quick dog brown The brown lazy brown
357+ ```
358+
359+ ` RandomList ` 继承了 ` ArrayList ` 的所有方法。本例中只添加了 ` select() ` 这个方法。
360+
262361<!-- Generic Interfaces -->
263362
264363## 泛型接口
0 commit comments