J2SE 5.0引入了许多新型的集合API-你需要了解它们以便能够正确地实现泛型定制的集合-它可以无缝地与多种类型和新型的"for each"结构一起工作。本文将向你展示示怎样创建与J2SE最新特征相兼容的集合。

一、 创立支撑泛型的类

用J2SE 5.0创立定制的泛型调集  J2SE 泛型 集合 Java 第1张

首要,你有必要学习怎样创立一个答应存在"泛型类型"的类。这意味着不管何时实例化你的类,你都能够指定一个或多个Java类型与该类相关联。为了阐明这个问题,请考虑列表1中的一个简略示例类。

留意,列表1中的类是怎样声明的。它在尖括号之间指定三个泛型。这些泛型是实在类型的占位符。当你声明一个这种类型的类时,你能够指定一个类来替代ONE,TWO和THREE。假如你不这样做,那么该类将运用Object的默许类型。

这个类显现出怎样规划一个类来接纳三个泛型类型。当你创立一个这种类型的类时你要支撑精确的类型。

列表1.泛型类:

package com.heatonresearch.examples.collections;
public class Example {
 private ONE one;
 private TWO two;
 private THREE three;
 public ONE getOne() { return one; }
 public void setOne(ONE one) { this.one = one; }
 public THREE getThree() { return three; }
 public void setThree(THREE three) { this.three = three; }
 public TWO getTwo() { return two; }
 public void setTwo(TWO two) { this.two = two; }
 public static void main(String args[]) {
  Example example = new
  Example();
  example.setOne(1.5);
  example.setTwo(2);
  example.setThree("Three");
 }
}

下面是怎样实例化一个Example类型的类的景象:

Example example=new Example();

前面的代码将替代详细的Double,Integer和String类型-适当于在列表1中的"ONE"、"TWO"和"THREE"占位符。你能够看到这些变量都有这些类型,经过下面三行设置它们的值。

example.setOne(1.5);
example.setTwo(2);
example.setThree("Three");

现在,已然你现已知道怎样创立一个运用泛型的定制类,那么创立一个运用泛型的定制调集类则更为简略些。

二、 创立一个Queue类

一个行列是一个很有用的数据结构。为了了解一个行列的功用,你能够想像在一个文娱公园人们排队骑马的景象。人们从队的后边进入到队中。为此,他们等候而***抵达部队的前端。其次序不能改动。

这种景象能够被应用到一个行列类上去。它共有两个办法,分别是"push"和"pop"。你运用push办法来把目标放置到行列中,而运用pop办法从行列中删去一项。例如,假如你运用push办法把三个目标添加到行列上,那么接连调用pop三次将以相同次序从行列中删去这三个元素。这正与文娱公园的景象相一致。假如有三个人以一特定的次序进入队中,他们将以相同的次序得到骑马文娱。

下列代码显现出怎样完成一个运用泛型的Java行列。

package com.heatonresearch.examples.collections;
import java.util.*;
public class Queue {
private ArrayList list = new ArrayList();
public void push(T obj) { list.add(obj); }
public T pop() throws QueueException {
if (size() == 0)
throw new QueueException(
"Tried to pop something from the queue, " +
"when it was empty");
T result = list.get(0);
list.remove(0);
return result;
}
public boolean isEmpty() { return list.isEmpty(); }
public int size() { return list.size(); }
public void clear() { list.clear(); }
}

前面的代码声明晰行列类,这样它能够接纳一个泛型类型。

public class Queue

泛型类型"T"是该类类型-它将被放入到该行列中去。为了把这些项存储到一个行列中,该类还要创立一个接纳"T"类型的ArrayList。
push办法很简略的。它接纳单一的类型为泛型"T"的目标,而且把它添加到ArrayList上。

pop办法略微杂乱些。首要,假如你要从行列中弹出一个目标,而且假如在行列中没有目标,那么该类将抛出一个QueueException类型的反常。下面是QueueException类。

package com.heatonresearch.examples.collections;
public class QueueException extends Exception {
 public QueueException(String msg) {
  super(msg);
 }
}

下面是抛出QueueException类型反常的代码:

if (size() == 0)
throw new QueueException("Tried to pop something from the queue, " +
"when it was empty");

假如行列不空,该办法将从行列中检索***一个元素,在一个名叫result的变量中存储它,然后从该列表中删去这个项。下面几行代码完成了这一功用:

T result = list.get(0);
list.remove(0);
return result;

留意,该暂时变量也是泛型类型"T"。当这个类与实在的代表泛型类型的Java类型一同运用时,为了完成***程度上的兼容性,不管你何时存取这些变量,确保总是运用泛型类型是非常重要的

#p#

三、 测验Queue类

下列类用于测验"泛型"行列。

package com.heatonresearch.examples.collections;
 public class TestQueue {
  public static void main(String args[]) {
   Queue queue = new Queue();
   queue.push(1);
   queue.push(2);
   queue.push(3);
   try {
    System.out.println("Pop 1:" + queue.pop());
    System.out.println("Pop 2:" + queue.pop());
    System.out.println("Pop 3:" + queue.pop());
   }
   catch (QueueException e) { e.printStackTrace(); }
  }
 }

前面的代码中创立的行列仅接纳整型目标。

Queue queue = new Queue();

接下来的测验把三个整数添加到该行列上。

Example example=new Example();0

留意,添加到该行列中的这些数字都是原始的类型。由于J2SE的主动装箱特性,这些原始的int类型被主动地转变成Integer目标。

接下来,该测验运用pop办法检索目标。在该行列为空的状况下,该测验捕获到QueueException反常。从行列中弹出三个数字的结果是:

Example example=new Example();1

虽然在这里作为一接纳的整数行列显现,可是由于泛型,所以行列类关于任何Java目标状况都能正常作业。

四、 创立一个可预知的Stack调集

这里是一个更杂乱的调集类型-它完成了一个仓库以使你在实践删去一个目标之前能够预知或"可偷看"。你能够或许经过运用一个迭代算子或运用J2SE 5.0的新的"for each"结构句子来进行预知。

这个PeekableStack类是一个先进后出(FILO)栈-让你遍历当时栈中的内容。它的完成运用了两个类。首要,PeekableStack类完成实践的栈部分。其次,PeekableStackIterator类完成一个"Java规范的"Iterator类-你能够用它来遍历整个栈。列表2(见所附源代码文件)显现出PeekableStack类的详细编码。

留意,列表2中的PeekableStack类完成了Iterable接口。这关于支撑新式的J2SE 5.0"for-each"结构句子是必要的。该Iterable接口用于指定你的调集支撑"iterator"办法-它回来一个迭代算子。假如没有这个接口,你的类将无法与新式的"for-each"结构句子相兼容。

这个可预知的栈包括push和pop办法,就象行列相同。该push办法仅仅是比行列略微杂乱些。而push办法担任把目标添加到栈上去并添加版本数(version)。

这个version变量答应PeekableStackIterator类确保没有修正操作产生。在迭代算子创立时,这个算子保存一份当时版本数。假如栈上经过调用push办法产生任何改动,那么这个版本数就不会匹配;此不匹配将导致算子抛出一个ConcurrentModificationException反常。

pop办法略微杂乱些。首要,它有必要决定在该列表中的***一个元素,这是经过取得列表的巨细而且减去1而得到的。

Example example=new Example();2

假如这个结果是一个小于零的数字,那么该栈便是空的,因而pop办法就回来null。

Example example=new Example();3

假如在栈中存在***一个元素,那么就从列表中检索它。在从列表中成功地检索这个项后,你能够把它删去。

Example example=new Example();4

***,回来从列表中检索的目标。

Example example=new Example();5

为支撑"for each"迭代,PeekableStack类的iterator办法回来一个"Java规范的"Iterator类-你能够用它来遍历包括在栈中的一切目标。iterator办法创立一个新的iterator而且回来之。

Example example=new Example();6

如你所见,该iterator类接纳当时栈和栈的项目列表作为结构器参数。这些值将为PeekableStackIterator所用-下一节将评论之。

五、 创立一个可预知的Stack迭代算子

假如PeekableStack类将要同Java中新的"for each"结构句子一同运用,那么你有必要创立一个"Java规范的"Iterator。列表3显现出一个PeekableStackIterator类的完成。

在列表3中,迭代子实践上并没有以任何方法改动栈的值;代之的是,该迭代子追寻它在元素列表中的当时方位而且总是回来下一个元素。由于这个信息被存储在iteration类自身,所以有或许存在多个算子运转于相同的栈上。

下列程序用于测验可预知的栈。

Example example=new Example();7

如你所见,有三个项被添加到栈上去。然后,这三个项被运用新的"for each"结构句子显现出来。

Example example=new Example();8

因而,你看到怎样成功地完成一调集-它支撑新式的J2SE常规-既有泛型也有"for each"结构句子。如你所见,创立与J2SE 5.0中新式的结构相兼容的调集是适当简单的-这只需求运用泛型而且完成恰当的接口即可。你会发现这样的调集类被无缝地集成到J2SE 5.0中。

【修改引荐】

  1. Java中泛型的了解与等价完成
  2. 关于Java 泛型的根本运用简介
  3. 泛型编程与规划新思维
    转载请说明出处
    知优网 » 用J2SE 5.0创立定制的泛型调集

    发表评论

    您需要后才能发表评论