您的位置:首页 > 职场人生

黑马程序员--第一阶段5.JavaAPI--第15天

2012-04-25 11:02 106 查看
--------------------
android培训、java培训、期待与您交流!--------------------

Hashtable与Properties类

Hashtable也是一种高级数据库结构,用来快速检索数据。Hashtable不仅可以像Vector一样动态存储一系的对象,而且对存储的每一个对象(称之为值)都要安排另一个对象(称之为关键字)与之相关联。

向Hashtable对象中存储数据,使用的是Hashtable.put(Object key,Object value)方法,从Hashtable中检索数据,使用Hashtable.get(Object
key)方法。值和关键字都可以是任何类型的非空的对象。Hashtable中的关键字不能相同

Hashtable numbers=new Hashtable();

numbers.put(“one”,new Integer(1));

numbers.put(“two”,new Integer(2));

numbers.put(“three”,new Integer(3));

要检索其中”tow”关键字对应的数据,看下面的代码就能明白:

Integer n=(Integer)numbers.get(“two”);

if(n!=null)

{

System.out.println(“two = ”+n);

}

想要成功地从Hashtable中检索数据,用作关键字的对象必须正确覆盖了Object.hashCode方法和Object.equals方法。覆盖Object.equals道理不难想象,检索数据时必须比较所用关键字是否与存储在Hashtable中的某个关键字相等,如果两个关键字对象不能正确判断是否相等,检索是不可能正确的。Object.hashCode方法返回一个叫散列码的值,这个值是由对象的地址以某种方式转换来的。内容相同的两个对象,既然是两个对象,地址就不可能一样,所以Object.hashCode返回的值也不一样。要想两个内容相同的Object子类对象的hashCode方法返回一样的散列码,子类必须覆盖Object.hashCode方法。用于关键字的类,如果它的两个String对象的内容不相等,它们的hashCode的返回值也不相等,如果两个String对象的内容相等,它们的hashCode的返回值也相等,所以,我们在实现自己编写的关键字类的hashCode方法时,可以调用这个关键字类的String类型的成员变量的hashCode方法来计算关键字类的hashCode返回值。注意:StringBuffer类没有按照关键字类的要求覆盖hashCode方法,即使两个StringBuffer类对象的内容相等,但这两个对象的hashCode方法返回值却不相等。所以,我们不能用StringBuffer作为关键字类。

实例:

MyKey.java

class MyKey

{

private String name;

private int age;

public MyKey(String name,int age)

{

this.name=name;

this.age=age;

}

public String toString()

{

return new String(name+","+age);

}

public boolean equals(Object obj)

{

if(obj instanceof MyKey)

{

MyKey objTem=(MyKey)obj;

if(name.equals(objTem.name)&&age==objTem.age)

return true;

else

return false;

}

else

return false;

}

public int hashCode()

{

return name.hashCode()+age;

}

}

上面的代码实现了我们的目的:如果两个人名字和年龄都相同,我们就认为他们是同一个人。

下面的类使用MyKey 类作为关键字类,取出所有关键字的集合和取出所有值的集合:

HashtableTest.java

import java.util.*;

public class HashtableTest

{

public static void main(String[] args)

{

Hashtable numbers=new Hashtable();

numbers.put(new MyKey("Zhangsan",18),new Integer(1));

numbers.put(new MyKey("Lisi",15),new Integer(2));

numbers.put(new MyKey("Wangwu",20),new Integer(3));

Enumeration e=numbers.keys();//Hashtable中的keys方法以Enumeration接口的方式返回Hashtable对象的所有关键字

while(e.hasMoreElements())

{

MyKey key=(MyKey)e.nextElement();

System.out.print(key+"=");//打印key时,会默认调用key.toString()方法,这个方法里面是什么内容打印出来的就是什么内容

System.out.println(numbers.get(key));//在MyKey类中重写的equals与hashCode方法是在这个get方法使用时要调用的,由系统自动调用

}

System.out.println(numbers.get(new MyKey("Wangwu",20)));//新建一个对象作为关键字传给get方法,用于取出numbers对象中的这个关键字所对应的值

//如果没有在MyKey类中覆盖equals、hashCode方法,则取不出对应的值

testABC abc=new testABC();

System.out.println(abc);//打印abc对象时,会默认调用这个对象的toString()方法,这个方法里面是什么内容打印出来的就是什么内容

}

}

class testABC

{

String a="戴振良";

String b="你好";

public String toString()

{

return a+b;

}

}

Properties
Properties是Hashtable的子类,它增加了将Hashtable对象中的关键字、值保存到文件和文件中读取关键字、值到Hashtable对象中的方法。在大多数应用程序都有选项设置,就是在程序退出时将功能/设置值存储到文件,程序启动时将功能/设置值读取到了内存,程序按新的设置运行,如:



如果要用Properties.store方法存储Properties对象中的内容,每个属性的关键字和值都必须是String类型。

实例:编写一个程序,每次运行时打印出运行的次数。

import java.util.Properties;

import java.io.*;

public class PropertiesFile

{

Properties settings=new Properties();

try{ //FileInputStream类:从文件系统中的某个文件中获得输入字节,该类是InputStream类的子类

settings.load(new FileInputStream("count.txt"));}//load( )方法功能:从输入流中读取属性列表(键和元素对)

catch(Exception e){

settings.setProperty("count",String.valueOf(0)); //setProerty方法是调用Hashtable的put方法,但是这个方法的参数必须是String类型的。这里把0转换为String对象用String.valueOf
方法,这比new Integer(0).toString()方法要方便,而String.valueOf方法实际上是调用Integer的toString方法来进行转换的

}

//settings.get("count");//get方法是从Hashtable中继承来的,该方法返回的值是Oject类型的

//getProperty方法与get方法功能类似,只不过getProperty方法返回的值是String类型的

int c=Integer.parseInt(settings.getProperty("count"))+1;

System.out.println("这是第"+c+"次运行");

//settings.put("count",new Integer(c).toString());//这个方法可以接受非字符串的数据作为参数,因为Properties中存储的关键字和值都必须是字符串,所以用下面的setProperty方法比较好。

settings.setProperty("count",new Integer(c).toString());//这个方法的参数必须都是字符串类型的

try{

settings.store(new FileOutputStream("count.txt"),"Program is used:");//在这句代码里,如果系统中没有count.txt文件存在,则系统会自动产生这个文件

}

catch(Exception a){

a.printStackTrace();

}

}

}

程序每次启动时都去读取那个记录文件,直接取出文件中所记录的运行次数并加1后,又重新将新的运行次数存回文件。由于第一次运行时硬盘上还没有那个记录文件,程序去读取那个记录文件时会报出一个异常,我们就在处理异常的语句中将属性的值设置为0,表示程序以前还没有运行过。如果要用到Properties类的store方法进行存储,每个属性的关键字和值都必须是字符串类型的,所以上面的程序没有用从父类Hashtable继承到的put、get方法进行属性的设置与读取,而直接用了Properties类的setProperty、getProperty方法进行属性的设置与读取。一般有使用次数限制的共享软件的程序代码基本上都是这么做的,只不过它们把记录次数的这个文件隐藏在某个不容易发现的地方,例如保存在注册表里或某个系统文件里,只要找到这个地方,删除这个文件或注册表项,这个软件又可以被使用了。

System类与Runtime
System类

java不支持全局函数和变量,java设计者将一些系统相关的重要函数和变量收集到了一个统一的类中,这就是System类,System类中的所有成员都是静态的,当我们要引用这些变量和方法时,直接使用System类名作前缀,如前面已经使用到的标准输入和输出的in和out变量。

System类的常用方法:

exit(int status)方法,提前终止虚拟机的运行。对于发生了异常情况而想终止虚拟机的运行,传递一个非零值作为参数。对于用户正常操作下想终止虚拟机的运行,则传递零作为参数。

currentTimeMillis方法返回自1970年1月1日0点0分0秒起至今的以毫秒为单位的时间,这是一个long类型的大数值,在计算机内部,只有数值,没有真正的日期类型及其他各种类型,也就是说,我们平常用到的日期本质上就是一个数值,但是通过这个数值,能够推算出其对应的具体日期时间。

可以用currentTimeMillis方法检测一段程序代码运行时所花费的时间:

long startTime=System.currentTimeMillis( );

…… //代码段

long endTime=System.currentTimeMillis( );

System.out.println(“总计用时:”+(endTime-startTime)+”毫秒”);

getProperties方法与Java的环境属性

getProperties方法获得当前Java虚拟机的系统属性。如果大家明白Windows的环境属性,如path和classpath就是其中的两个环境变量,每一个属性都是变量与值成对的形式出现的。

setProperties方法设置当前Java虚拟机的系统属性。

getProperties、setProperties这两个方法返回值和参数分别是Properties类的一个实例。Properties实例对象中存储着Java虚拟机所有的系统属性的变量和值对的情况。

同样的道理,Java作为一个虚拟的操作系统,它也有自己的环境属性,Properties是Hashtable的子类,正好可以用于存储环境属性中的多个变量、值成对格式的数据,getProperties方法返回值是包含了当前虚拟机的所有环境属性的Properties类型的对象。

实例:打印出当前虚拟机的所有环境属性的变量和值。

import java.util.*;//Properties位于此包中

public class TestProperties {

public static void main(String args[]){

System.setProperty("haha","hello");//增加系统属性,第一个参数为变量名,第二个为值

Properties sp=System.getProperties();//获取当前java虚拟机的系统属性

Enumeration e=sp.propertyNames();//获取所有的属性名称

while(e.hasMoreElements()){

String key=(String)e.nextElement();//获取e中的元素,也就是java虚拟机的系统属性名称

System.out.println(key+"="+sp.getProperty(key));//输出(名称+"="+值)

}

Process p=null; //Process类代表Java虚拟机启动的进程启动的子进程

try{

p=Runtime.getRuntime().exec("notepad.exe TestProperties.java");

Thread.sleep(5000);//进程睡眠5秒

}

catch(Exception a){

a.printStackTrace();

}

p.destroy();//这个方法为关闭实例p所对应的进程

}

}

在Windows中,很容易增加一个新的环境属性,但如何为Java虚拟机增加一个新的环境属性呢?在命令行窗口中直接运行Java命令,会看到有一个“-D<name>=<value>格式的选项可以设置新的系统环境属性。如:

java –Dname=hello TestProperties

增加两个环境属性的格式:java –DAAA=bbb –DCCC=ddd TestProperties

Runtime类
Runtime类封装了Java命令本身运行的进程,也就是封装了Java虚拟机进程,一个Java
虚拟机对应一个Runtime实例对象,其中的许多方法与System中的方法相重复。不能直接创建Runtime实例,但是可以通过静态方法Runtime.getRuntime获得正在运行的Runtime对象的引用。

Exec方法,Java命令运行后,本身是多任务操作系统上的一个进程,在这个进程中启动一个新的进程(这个进程就叫子进程),即执行其他程序时使用exec方法。exec方法返回一个代表子进程的Process类对象,通过这个对象,Java进程可以与子进程交互。

实例:

运行后程序启动一个子进程:用Windows的记事本程序打开了我们的源程序,并在5秒种后销毁该子进程,记事本程序被关掉。

public class TestRunTime {

public static void main(String [] args) {

Process p=null; //Process类代表Java虚拟机启动的进程启动的子进程

try{

p=Runtime.getRuntime().exec("notepad.exe TestRuntime.java");

Thread.sleep(5000);//把线程暂停5秒

}catch(Exception e){

System.out.println(e.getMessage());

}

p.destroy();//这个方法为关闭实例p所对应的进程

}

}

由于程序不能直接创建类Runtime的实例,所以可以保证我们只会产生一个Runtime的实例对象,而不能产生多个实例对象,这种情况就是单态设计模式。我们可以按照单态设计模式思想来设想一下Runtime类在内部是如何构造Runtime类的对象实例的。

--------------------
android培训、java培训、期待与您交流!--------------------
[align=center] 详情请查看:http://edu.csdn.net/heima/[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: