在java中提供了一个散列表类Hashtable利用该类我们可以按照特定的方式来存储数据从而达到快速检索的目的本文以查询股票的收盘数据为例详细地说明java中散列表的使用方法
一散列表的原理
散列表又称为哈希表是线性表中一种重要的存储方式和检索方法在散列表中可以对节点进行快速检索散列表算法的基本思想是由结点的关键码值决定结点的存储地址即以关键码值k为自变量通过一定的函数关系h(称为散列函数)计算出对应的函数值h(k)来将这个值解释为结点的存储地址将结点存入该地址中检索时根据要检索的关键码值用同样的散列函数计算出地址然后到相应的地址中去获取要找的结点数据因此散列表有一个重要特征平均检索的长度不直接依赖于表中元素的个数
散列表最重要的一个指标是负载因子即散列表中结点数目与表中能容纳的总结点数的比值它描述了散列表的饱和程度负载因子越接近内存的使用效率越高元素的寻找时间越长同样负载因子越接近元素的寻找时间越短但内存的浪费越大Hashtable类缺省的负载因子为
二Hashtable类
Hashtable类为我们提供了散列表完整的功能可以让我们很方便地构造和使用散列表查询信息
创建散列表对象
Hashtable类的构造器主要有下面几种形式
public Hashtable(int initialCapacity float loadFactor)
public Hashtable(int initialCapacity)
public Hashtable()
在本文的实例中我们使用了最简单的一种
Hashtable stockInfo = new Hashtable();
充填数据
当构造了Hashtable对象后我们就可以将数据填入该对象中以便以后查询Hashtable类提供了put方法来完成数据的装填其原型如下
public synchronized Object put(Object key Object value)
查询数据
查询数据可以使用get方法其原型如下
public synchronized Object get(Object key)
其它常用的方法
public int size();
//返回散列表中的结点数目
public boolean isEmpty();
//判断散列表是否为空
public boolean containsValue(Object value);
//判断散列表中是否含有某值
public synchronized boolean containsKey(Object key);
//判断散列表中是否含有某个结点
public synchronized void clear();
//清空整个散列表
三StringTokenizer类
StringTokenizer类的主要用途是将字符串以定界符为界分析为一个个的token(可理解为单词)定界符可以自己指定
构造器有下面几种形式
public StringTokenizer(String str
String delim boolean returnTokens);
public StringTokenizer(String str String delim);
public StringTokenizer(String str);
其中str为需分析的字符串delim为定界符
Tokens描述是否将定界符作为一个token
其它常用的方法有
public boolean hasMoreTokens() ;
//判断字符串中是否还有token
public String nextToken();//
StringTokenizer对象的下一个token
四实例
本文使用的股票行情为上海和深圳证券交易所的收盘行情文件名为hqsjtxt下面是文件中的一行数据
宏图高科
下面是完整的源程序在JDK下使用javac编译通过
import javaio*;
import javautil*;
import javaawt*;
import javaapplet*;
import javaawtevent*;
public class StockQuote extends Applet
implements ActionListener
{
private static final File INFO_FILE =
new File(hqsjtxt);
private Hashtable stockInfo;
TextField stockID;
Button button;
private String quoteidquotename;
public void init()
{
add(new Label(股票代码));
stockID = new TextField();
add(stockID);
button = new Button(查询);
buttonaddActionListener(this);
add(button);
resize( );
}
public void start()
{
loadinfo();
}
protected boolean loadinfo()
{
String fileLine;
StringTokenizer tokenize;
String id;
StringBuffer name;
try {
// 创建一个访问数据文件的stream
BufferedReader stockInput = new
BufferedReader(new FileReader(INFO_FILE));
// 创建Hashtable对象
stockInfo = new Hashtable();
// 每次从文件中读一行数据
while ((fileLine = stockInputreadLine()) != null) {
// 将每一行数据分解为tokens
tokenize = new StringTokenizer(fileLine);
try {
id = tokenizenextToken();
// 创建一个放置股票信息的buffer
name = new StringBuffer();
while(tokenizehasMoreTokens()) {
nameappend(tokenizenextToken());
if (tokenizehasMoreTokens()) {
nameappend();
}
}
// 向Hashtable中充填记录
stockInfoput(idnametoString());
} catch(NullPointerException excpt) {
Systemerrprintln(充填数据时出错: + excpt);
} catch(NoSuchElementException excpt) {
Systemerrprintln(无效的数据记录 +
in file: + excpt);
}
}
stockInputclose();
} catch(FileNotFoundException excpt) {
Systemerrprintln(不能发现文件: + excpt);
return false;
} catch(IOException excpt) {
Systemerrprintln(I/O故障: + excpt);
return false;
}
return true;
}
protected String getQuote(String StockID)
{
String info;
// 从Hashtable得到数据
info = (String)stockInfoget(StockID);
if (info != null)
return info;
else
return 股票代码错误!;
}
public void paint(Graphics g)
{
gdrawString(股票代码+quoteid+: );
gdrawString(股票名称+前收+今开+最高
+最低+收盘+交易量+交易金额 );
gdrawString(quotename );
}
public void actionPerformed(ActionEvent ev)
{
String label = evgetActionCommand();
if (labelequals(查询))
{
quoteid = stockIDgetText();
if(quoteid != null)
quotename = getQuote(quoteid);
else quotename = 请输入股票代码!;
repaint();
}
}
}
由于java固有的安全方面的限制如果不使用SecurityPermission或数字签名等措施java程序就不具有读取本地文件的权限为了节省篇幅本文对此不再多做讨论将编译得到的StockQuoteclass放到一l文件中直接使用jdk提供的appletviewer其命令行的使用方法如下
d:\jdk\bin\appletviewer l