??xml version="1.0" encoding="utf-8" standalone="yes"?> 常常在网上看到有问:如何?java E序~译?.exe 文g。通常回答只有两种Q一U是制作一个可执行?JAR 文g包,然后可以像.chm 文一样双击运行了Q而另一U是使用 JET 来进?~译。但?JET 是要用钱买的Q而且据说 JET 也不是能把所有的 Java E序都编译成执行文gQ性能也要打些折扣。所以,使用制作可执?JAR 文g包的Ҏ是最佳选择了,何况它还能保持Java 的跨q_Ҏ? 1. JAR 文g?
下面来看看什么是 JAR 文g包吧Q?
JAR 文g是 Java Archive FileQ顾名思意Q它的应用是?Java 息息相关的,?Java 的一U文档格式。JAR 文g非常cM ZIP 文g——准的_它就?ZIP 文gQ所以叫它文件包。JAR 文g?ZIP 文g唯一的区别就是在 JAR 文g的内容中Q包含了一?META-INF/MANIFEST.MF 文gQ这个文件是在生?JAR 文g的时候自动创建的。D个例子,如果我们h如下目录l构的一些文Ӟ
==
`-- test
`-- Test.class
把它压羃?ZIP 文g test.zipQ则q个 ZIP 文g的内部目录结构ؓQ?
test.zip
`-- test
`-- Test.class
如果我们使用 JDK ?jar 命o把它打成 JAR 文g?test.jarQ则q个 JAR 文g的内部目录结构ؓQ?
test.jar
|-- META-INF
| `-- MANIFEST.MF
`-- test
`--Test.class
2. 创徏可执行的 JAR 文g?
制作一个可执行?JAR 文g包来发布你的E序?JAR 文g包最典型的用法?
Java E序是由若干?.class 文gl成的。这?.class 文g必须Ҏ它们所属的包不同而分U分目录存放Q运行前需要把所有用到的包的根目录指定给 CLASSPATH 环境变量或?java 命o?-cp 参数Q运行时q要到控制台下去使用 java 命o来运行,如果需要直接双击运行必d Windows 的批处理文g (.bat) 或?Linux ?Shell E序。因此,许多QJava 是一U方便开发者苦了用LE序设计语言?
其实不然Q如果开发者能够制作一个可执行?JAR 文g包交l用P那么用户使用h方便了。在 Windows 下安?JRE (Java Runtime Environment) 的时候,安装文g会将 .jar 文g映射l?javaw.exe 打开。那么,对于一个可执行?JAR 文g包,用户只需要双d可以运行程序了Q和阅读 .chm 文一h?(.chm 文默认是由 hh.exe 打开?。那么,现在的关键,是如何来创个可执行?JAR 文g包?
创徏可执行的 JAR 文g包,需要用带 cvfm 参数?jar 命oQ同样以上述 test 目录ZQ命令如下:
jar cvfm test.jar manifest.mf test
q里 test.jar ?manifest.mf 两个文gQ分别是对应的参?f ?mQ其重头戏在 manifest.mf。因创徏可执行的 JAR 文g包,光靠指定一?manifest.mf 文g是不够的Q因?MANIFEST ?JAR 文g包的特征Q可执行?JAR 文g包和不可执行?JAR 文g包都包含 MANIFEST。关键在于可执行 JAR 文g包的 MANIFESTQ其内容包含?Main-Class 一V这?MANIFEST 中书写格式如下:
Main-Class: 可执行主cd?包含包名)
例如Q假设上例中?Test.class 是属?test 包的Q而且是可执行的类 (定义?public static void main(String[]) Ҏ)Q那么这?manifest.mf 可以~辑如下Q?
Main-Class: test.Test <回R>
q个 manifest.mf 可以攑֜M位置Q也可以是其它的文g名,只需要有 Main-Class: test.Test 一行,且该行以一个回车符l束卛_。创Z manifest.mf 文g之后Q我们的目录l构变ؓQ?
==
|-- test
| `-- Test.class
`-- manifest.mf
q时候,需要到 test 目录的上U目录中M?jar 命o来创?JAR 文g包。也是在目录树中用?=”表C的那个目录中,使用如下命oQ?
jar cvfm test.jar manifest.mf test
之后在?=”目录中创徏?test.jarQ这?test.jar 是执行?JAR 文g包。运行时只需要?java -jar test.jar 命o卛_?
需要注意的是,创徏?JAR 文g包中需要包含完整的、与 Java E序的包l构对应的目录结构,像上例一栗?Main-Class 指定的类Q也必须是完整的、包含包路径的类名,如上例的 test.TestQ而且在没有打?JAR 文g包之前可以?java <cd> 来运行这个类Q即在上例中 java test.Test 是可以正运行的 (当然要在 CLASSPATH 正确的情况下)?
3. jar 命o详解
jar 是随 JDK 安装的,?JDK 安装目录下的 bin 目录中,Windows 下文件名?jar.exeQLinux 下文件名?jar。它的运行需要用?JDK 安装目录?lib 目录中的 tools.jar 文g。不q我们除了安?JDK 什么也不需要做Q因?SUN 已经帮我们做好了。我们甚至不需要将 tools.jar 攑ֈ CLASSPATH 中?
使用不带M?jar 命o我们可以看到 jar 命o的用法如下:
jar {ctxu}[vfm0M] [jar-文g] [manifest-文g] [-C 目录] 文g?...
其中 {ctxu} ?jar 命o的子命oQ每?jar 命o只能包含 ctxu 中的一个,它们分别表示Q?
-c 创徏新的 JAR 文g?
-t 列出 JAR 文g包的内容列表
-x 展开 JAR 文g包的指定文g或者所有文?
-u 更新已存在的 JAR 文g?(d文g?JAR 文g包中)
[vfm0M] 中的选项可以任选,也可以不选,它们?jar 命o的选项参数
-v 生成详细报告q打印到标准输出
-f 指定 JAR 文g名,通常q个参数是必ȝ
-m 指定需要包含的 MANIFEST 清单文g
-0 只存储,不压~,q样产生?JAR 文g包会比不用该参数产生的体U大Q但速度更快
-M 不生所有项的清单(MANIFEST〕文Ӟ此参C忽略 -m 参数
[jar-文g] 即需要生成、查看、更新或者解开?JAR 文g包,它是 -f 参数的附属参?
[manifest-文g] ?MANIFEST 清单文gQ它?-m 参数的附属参?
[-C 目录] 表示转到指定目录下去执行q个 jar 命o的操作。它相当于先使用 cd 命o转该目录下再执行不带 -C 参数?jar 命oQ它只能在创建和更新 JAR 文g包的时候可用?
文g?... 指定一个文?目录列表Q这些文?目录是要添加到 JAR 文g包中的文?目录。如果指定了目录Q那?jar 命o打包的时候会自动把该目录中的所有文件和子目录打入包中?
下面举一些例子来说明 jar 命o的用法:
1) jar cf test.jar test
该命令没有执行过E的昄Q执行结果是在当前目录生成了 test.jar 文g。如果当前目录已l存?test.jarQ那么该文g被覆盖?
2) jar cvf test.jar test
该命令与上例中的l果相同Q但是由?v 参数的作用,昄Z打包q程Q如下:
标明清单(manifest)
增加Qtest/(d= 0) (写出= 0)(存储?0%)
增加Qtest/Test.class(d= 7) (写出= 6)(压羃?14%)
3) jar cvfM test.jar test
该命令与 2) l果cMQ但在生成的 test.jar 中没有包?META-INF/MANIFEST 文gQ打包过E的信息也略有差别:
增加Qtest/(d= 0) (写出= 0)(存储?0%)
增加Qtest/Test.class(d= 7) (写出= 6)(压羃?14%)
4) jar cvfm test.jar manifest.mf test
q行l果?2) 怼Q显CZ息也相同Q只是生?JAR 包中?META-INF/MANIFEST 内容不同Q是包含?manifest.mf 的内?
5) jar tf test.jar
?test.jar 已经存在的情况下Q可以查?test.jar 中的内容Q如对于 2) ?3) 生成?test.jar 分别应该此命令,l果如下Q?
对于 2)
META-INF/
META-INF/MANIFEST.MF
test/
test/Test.class
对于 3)
test/
test/Test.class
6) jar tvf test.jar
除显C?5) 中显C的内容外,q包括包内文件的详细信息Q如Q?
0 Wed Jun 19 15:39:06 GMT 2002 META-INF/
86 Wed Jun 19 15:39:06 GMT 2002 META-INF/MANIFEST.MF
0 Wed Jun 19 15:33:04 GMT 2002 test/
7 Wed Jun 19 15:33:04 GMT 2002 test/Test.class
7) jar xf test.jar
解开 test.jar 到当前目录,不显CZQ何信息,对于 2) 生成?test.jarQ解开后的目录l构如下Q?
==
|-- META-INF
| `-- MANIFEST
`-- test
`--Test.class
jar xvf test.jar
q行l果?7) 相同Q对于解压过E有详细信息昄Q如Q?
创徏QMETA-INF/
展开QMETA-INF/MANIFEST.MF
创徏Qtest/
展开Qtest/Test.class
9) jar uf test.jar manifest.mf
?test.jar 中添加了文g manifest.mfQ此使用 jar tf 来查?test.jar 可以发现 test.jar 中比原来多了一?manifest。这里顺便提一下,如果使用 -m 参数q指?manifest.mf 文gQ那?manifest.mf 是作为清单文?MANIFEST 来用的Q它的内容会被添加到 MANIFEST 中;但是Q如果作Z般文件添加到 JAR 文g包中Q它跟一般文件无异?
10) jar uvf test.jar manifest.mf
?9) l果相同Q同时有详细信息昄Q如Q?
增加Qmanifest.mf(d= 17) (写出= 19)(压羃?-11%)
4. 关于 JAR 文g包的一些技?
1) 使用 unzip 来解?JAR 文g
在介l?JAR 文g的时候就已经说过了,JAR 文g实际上就?ZIP 文gQ所以可以用常见的一些解?ZIP 文g的工h解压 JAR 文gQ如 Windows 下的 WinZip、WinRAR {和 Linux 下的 unzip {。?WinZip ?WinRAR {来解压是因为它们解压比较直观,方便。而?unzipQ则是因为它解压时可以?-d 参数指定目标目录?
在解压一?JAR 文g的时候是不能使用 jar ?-C 参数来指定解压的目标的,因ؓ -C 参数只在创徏或者更新包的时候可用。那么需要将文g解压到某个指定目录下的时候就需要先这?JAR 文g拯到目标目录下Q再q行解压Q比较麻烦。如果?unzipQ就不需要这么麻烦了Q只需要指定一?-d 参数卛_。如Q?
unzip test.jar -d dest/
2) 使用 WinZip 或?WinRAR {工具创?JAR 文g
上面提到 JAR 文g是包含?META-INF/MANIFEST ?ZIP 文gQ所以,只需要?WinZip、WinRAR {工具创建所需?ZIP 压羃包,再往q个 ZIP 压羃包中d一个包?MANIFEST 文g?META-INF 目录卛_。对于?jar 命o?-m 参数指定清单文g的情况,只需要将q个 MANIFEST 按需要修改即可?
3) 使用 jar 命o创徏 ZIP 文g
有些 Linux 下提供了 unzip 命oQ但没有 zip 命oQ所以需要可以对 ZIP 文gq行解压Q即不能创徏 ZIP 文g。如要创Z?ZIP 文gQ用带 -M 参数?jar 命o卛_Q因?-M 参数表示制作 JAR 包的时候不d MANIFEST 清单Q那么只需要在指定目标 JAR 文g的地方将 .jar 扩展名改?.zip 扩展名,创徏的就是一个不折不扣的 ZIP 文g了,如将上一节的W?3) 个例子略作改动:
jar cvfM test.zip test
]]>
而Serializable接口属于支持序列化的一个接口,只有一个实现它的对象可以被序列化工具存储和回复QSerializable接口没有定义M成员Q只用来表示一个篏可以被序列化Q若该类可以序列化,那么它的所有子c都可以?
下面是关于序列化的一个实例:
E序名称QSerializationDemo.java
E序主题Q实现对象的序列化和反序列化
E序说明Q该E序由实例化一个MyClasscȝ对象开始,该对象有三个实例变量Q类型分别ؓString、int、doubleQ是希望存储和恢复的信息?/b>
import java.io.*;
public class SerializationDemo{
public static void main(String args[]){
//Object serialization
try{
MyClass object1=new MyClass("Hello",-7,2.7e10);
System.out.println("object1:"+object1);
FileOutputStream fos=new FileOutputStream("serial");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(object1);
oos.flush();
oos.close();
}
catch(Exception e){
System.out.println("Exception during serialization:"+e);
System.exit(0);
}
//Object deserialization
try{
MyClass object2;
FileInputStream fis=new FileInputStream("serial");
ObjectInputStream ois=new ObjectInputStream(fis);
object2=(MyClass)ois.readObject();
ois.close();
System.out.println("object2:"+object2);
}
catch(Exception e){
System.out.println("Exception during deserialization:"+e);
System.exit(0);
}
}
}
class MyClass implements Serializable{
String s;
int i;
double d;
public MyClass(String s,int i,double d){
this.s=s;
this.i=i;
this.d=d;
}
public String toString(){
return "s="+s+";i="+i+";d="+d;
}
}
E序q行l果Qobject1和object2的实例变量是一LQ输出如下:object1:s=Hello;i=-7;d=2.7E10
object2:s=Hello;i=-7;d=2.7E10
]]>
只要我们的class 实现了java.io.Serializable接口Q就可以利用ObjectOutputStream的writeObjectQ)Ҏ一个对象序列化Q利用ObjectInputStream的readObject()ҎQ可以返回读出的object对象。Serializable接口不需要我们实CQ何方法?br />
以下是一个例子,它能l我们一个感性的初步认识Q?br />
Serial实现了就java.io.Serializable接口Q是需要序列化的类。我们首先构造一个Serial的对象serial1然后其保存(序列?在一个文件中Q而后再将其读出(反序列化Q,q打印其内容?br />package Stream;
/**
* @author favo yang
*/
import java.io.*;
public class Serial implements Serializable {
int company_id;
String company_addr;
boolean company_flag;
public Serial(){}//不同于C++,没有也可?br />
public Serial(int company_id,String company_addr,boolean company_flag) {
this.company_id=company_id;
this.company_addr=company_addr;
this.company_flag=company_flag;
}
public static void main(String[] args) {
Serial serial1 = new Serial(752,"dayer street #5 building 02-287",false);//构造一个新的对?br />
FileInputStream in=null;
FileOutputStream out=null;
ObjectInputStream oin=null;
ObjectOutputStream oout=null;
try {
out = new FileOutputStream("5.txt");
oout = new ObjectOutputStream(out);
serial1.serialize(oout);//序列?br />
oout.close();
oout=null;
in = new FileInputStream("5.txt");
oin = new ObjectInputStream(in);
Serial serial2 = Serial.deserialize(oin);//反序列化
System.out.println(serial2);//打印l果
} catch (Exception ex){
ex.printStackTrace();
} finally{
try {
if (in != null) {
in.close();
}
if (oin != null) {
oin.close();
}
if (out != null) {
out.close();
}
if (oout != null) {
oout.close();
}
} catch (IOException ex1) {
ex1.printStackTrace();
}
}
}
/**
* deserialize
*/
public static Serial deserialize(ObjectInputStream oin) throws Exception{
Serial s=(Serial)oin.readObject();
return s;
}
public String toString() {
return "DATA: "+company_id+" "+company_addr+" "+company_flag;
}
/**
* serialize
*/
public void serialize(ObjectOutputStream oout) throws Exception{
oout.writeObject(this);
}
}
q行l果QDATA: 752 dayer street #5 building 02-287 false
正确打印了结果?br />
]]>
JDK 1.5 中引入了新的语言成分, 泛型(Generics)是其中较为重要的一?
单的泛型(Defining Simple Generics)
以下代码摘自java.util包的List接口和Iterator接口的定?
public interface List<E> {
void add(E x);
Iterator<E> iterator();
}
public interface Iterator<E> {
E next();
boolean hasNext();
}
cd参数
与尖括号有关的一些东西是JDK 5引入的新东西, 它们是List和Iterator接口?形式的类型参?(U?cd形参")声明.
而在Ҏ型声明Listq行调用?例如: List<Integer>), 所有出现的cd形参(?
E)的地? 都会?实际的类型参?(U?cd实参", ?Integer)所替换?
虽然与C++中的模板机制在Ş式上很想? 但必需注意, Java中的泛型声明决不会在调用时被展成多䆾副本: 不论是在源码U? 二进制, q是在磁盘或内存? 都不会被展开!
泛型声明只会也只需~译一? q生成一个类文g(class文g), q一点跟普通的cL接口完全一?
cd参数其实跟方法或构造器中所用的通常参数相类? 一个方法中可以声明它用以处理的"形式的值参?, 怼? 泛型声明也有?形式的类型参?; 当方法被调用? 实际参数会替换Ş式参? 然后执行Ҏ? 同样, 当泛型声明被调用? 实际的类型参C替换掉Ş式的cd参数.
关于命名U定的备? 推荐使用_而简?? 单个字符)的方式ؓ形式的类型参数命? 最好避免用小写字W? 以便与普通的cL接口的参数相区分开? 许多宣传品类型?E 表示其元素的cd形参.
2. 泛类型与子类型化(Generics and Subtyping)
先看以下两行代码是否合法:
List<String> ls = new ArrayList<String>(); // 1
List<Object> lo = ls; // 2
W一行没问题, 关键在第二行代码, 大多Ch会认? "一个String的List自然更是一个Object的List", 因此, W?行没问题.
? 接着看以下代?
lo.add(new Object()); // 3
String s = ls.get(0); // 4: 试图一个Object赋给一个String!
可见, 通过别名lo, 我们能对ls, 一个String的列? q行数据操作(特别是插入一个Object), 从而导致ls不仅仅是容纳了String对象! q是Java~译器不容许? ~译? W?行会报告一个编译错误的.
通常, 若Foo是Bar的一个子cd(子类或子接口), G是某个泛型声? 则G<Foo>q不是G<Bar>的一个子cd.
q一点往往是最难以理解? 因ؓ它和通常的直观相? 在直观的理解? 我们实际上假定了集合是不会变动的, 但java语言中则非如?
3. 通配(Wildcards)
假定要输Z个集合中的所有元? 以下分别是旧版本及新版本(JDK 1.5)中的写法:
void printCollection(Collection c) {
Iterator i = c.iterator();
for( k = 0; k < c.size(); k++) {
System.out.println( i.next() );
}}
void printCollection(Collection<Object> c) {
for(Object e : c) {
System.out.println(e);
}}
问题在于, 新版本反而不如旧版本更有用些. 因ؓ旧版本能使用各种cd的集合作为参? 但新版本则只能用Collection<Object>. 而正如上节看到的, Collection<Object>q不是其它各U集合的类?父类?.
所有集合的类型应该写? Collection<?>, M: collection of unknown(未知集合), 即一个集? 其元素类型可以与Mcd相匹? 因此U这U类型ؓ"通配cd".
正确实现上述旧版本的代码可以q么?
void printCollection(Collection<?> c) {
for(Object e : c) {
System.out.println(e);
}}
q时, 可以用Q意类型的集合来调用此Ҏ. 注意在方法体? 仍然?c 中读入元素ƈ赋给了Object, q是没有错误? 因此不论cd实参是何U集? 它的元素都是object. 然? 如果Ll它增加一个object则是不安全的:
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // ~译时的错误
׃我们不知道c的元素类型是什? 所以不能给它增加一个object. Ҏadd()接受一个类型E的参? 而E与集合的元素cd相同. 当类型实参是?? 它表C?未知的类?, 我们传递给add的参数必Lq个"未知cd"的子cd. 不幸的是, 既然cd未知, 也就无法军_其子cd, 于是什么也不能作ؓ其参? 唯一的例外是null, 因ؓnull是所有类型的一个成?
另一斚w, 如果l了一个List<?>, 我们可以调用get()Ҏq用其q回的元? 虽然q回的元素类型是"未知cd", 但它d是一个object, 因此get()q回的元素赋l一个Objectcd的变? 或将其传递给一个可接受Object的参数都是安全的.
一个对象的HashCode是一个简单的Hash法的实玎ͼ虽然它和那些真正的复杂的Hash法相比q不能叫真正的算法,它如何实现它Q不仅仅是程序员的编E水q问题,而是关系C的对象在存取是性能的非帔R要的关系.有可能,不同的HashCode可能会你的对象存取产生Q成百上千倍的性能差别?/p>
我们先来看一下,在JAVA中两个重要的数据l构:HashMap和HashtableQ虽然它们有很大的区别,如承关pM同,对value的约束条?是否允许null)不同Q以及线E安全性等有着特定的区别,但从实现原理上来_它们是一致的.所以,我们只以Hashtable来说?
在java中,存取数据的性能Q一般来说当然是首推数组Q但是在数据量稍大的容器选择中,Hashtable有比数l性能更高的查询速度.具体原因看下面的内容?/p>
Hashtable在存储数据时Q一般先作为key的对象的HashCode?x7FFFFFFF做与操作Q因Z个对象的HashCode可以敎ͼq样操作后可以保证它Z个正整数.然后以Hashtable的长度取模,得到值对象在Hashtable中的索引?/p>
index = (o.hashCode() & 0x7FFFFFFF)%hs.length;q个值对象就会直接放在Hashtable的第index位置Q对于写入,q和数组一P把一个对象放在其中的Windex位置Q但如果是查询,l过同样的算法,Hashtable可以直接通过key得到indexQ从Windex取得q个值对象,而数l却要做循环比较.所以对于数据量E大ӞHashtable的查询比数据h更高的性能?/p>
虽然不同对象有不同的hashcodeQ但不同的hashCodel过与长度的取余Q就很可能生相同的index?/p>
极端情况下会有大量的对象产生一个相同的索引.q就是关pHashtable性能问题的最重要的问?
Hash冲突?/p>
常见的Hash冲突是不同key对象最l生了相同的烦引,而一U非常甚至绝对少见的Hash冲突是,如果一l对象的个数大过了int范围Q而HashCode的长度只能在int范围中,所以肯定要有同一l的元素有相同的HashCodeQ这h论如何他们都会有相同的烦?当然q种极端的情冉|极少见的Q可以暂不考虑Q但是对于同的HashCodel过取模Q则会中相同的索引Q或者不同的对象却具有相同的HashCodeQ当然具有相同的索引?/p>
事实上一个设计各好的HashTableQ一般来说会比较q_地分布每个元素,因ؓHashtable的长度L比实际元素的个数按一定比例进行自?装填因子一般ؓ0.75)左右Q这样大多数的烦引位|只有一个对象,而很的位置会有几个元素.所以Hashtable中的每个位置存放的是一个链表,对于只有一个对象是位置Q链表只有一个首节点(Entry)QEntry的next为null.然后有hashCodeQkeyQvalue属性保存了该位|的对象的HashCodeQkey和value(对象本n)Q如果有相同索引的对象进来则会进入链表的下一个节?如果同一个烦引中有多个对象,ҎHashCode和key可以在该链表中找C个和查询的key相匹配的对象?/p>
从上面我看可以看刎ͼ对于HashMap和Hashtable的存取性能有重大媄响的首先是应该该数据结构中的元素尽量大可能h不同的HashCodeQ虽然这q不能保证不同的HashCode产生不同的indexQ但相同的HashCode一定生相同的indexQ从而媄响生Hash冲突?/p>
对于一个象Q如果具有很多属性,把所有属性都参与散列Q显然是一U笨拙的设计.因ؓ对象的HashCode()Ҏ几乎无所不在地被自动调用Q如equals比较Q如果太多的对象参与了散?那么需要的操作常数旉会增加很大.所以,挑选哪些属性参与散列绝Ҏ一个编E水q的问题?/p>
从实现来_一般的HashCodeҎ会这?
return Attribute1.HashCode() + Attribute1.HashCode()..[+super.HashCode()]?/p>
我们知道Q每ơ调用这个方法,都要重新Ҏ法内的参与散列的对象重新计算一ơ它们的HashCode的运,如果一个对象的属性没有改变,仍然要每ơ都q行计算Q所以如果设|一个标记来~存当前的散列码Q只要当参与散列的对象改变时才重新计,否则调用~存的hashCodeQ这可以从很大程度上提高性能?/p>
默认的实现是对象内部地址转化为整C为HashCodeQ这当然能保证每个对象具有不同的HasCodeQ因Z同的对象内部地址肯定不同(废话)Q但java语言q不能让E序员获取对象内部地址Q所以,让每个对象生不同的HashCode有着很多可研I的技术?/p>
如果从多个属性中采样hq_分布的hashCode的属性,q是一个性能和多h相矛盾的地方,如果所有属性都参与散列Q当然hashCode的多h将大大提高Q但牺牲了性能Q而如果只能少量的属性采h列,极端情况会生大量的散列冲突Q如??的属性中Q如果用性别而不是姓名或出生日期Q那只有两个或几个可选的hashcode|生一半以上的散列冲突.所以如果可能的条g下,专门产生一个序列用来生成HashCode是一个好的选择(当然产生序列的性能要比所有属性参与散列的性能高的情况下才行,否则q不如直接用所有属性散??/p>
如何对HashCode的性能和多h求得一个^衡,可以参考相关算法设计的书,其实q不一定要求非常的优秀Q只要能最大可能减散列值的聚集.重要的是我们应该记得HashCode对于我们的程序性能有着生要的媄响,在程序设计时应该时时加以注意?/p>
dir 列文件名 deltree 删除目录树 ?cls 清屏 cd 改变当前目录
copy 拯文g diskcopy 复制盘 del 删除文g format 格式化磁?br />edit 文本~辑 mem 查看内存状况 md 建立子目录 ?move Ud文g、改目录?br />more 分屏昄 type 昄文g内容 rd 删除目录 sys 制作DOSpȝ?br />ren 改变文g名 ?xcopy 拯目录与文件 ?chkdsk 查磁盘 ?attrib 讄文g属?br />fdisk 盘分区 date 昄及修改号期 ?label 讄h号 ?defrag 盘片整理
msd pȝ ?path 讄搜寻目录 share 文g׃n memmaker内存优化理
help 帮助 restore 恢复备䆾文g set 讄环境变量 time 昄及修Ҏ?br />tree 列目录树 debug 随机调试E序 doskey 重新调用DOS命o prempt 讄提示W?undelete恢复被删的文件 ?scandisk、修理磁盘 ?
不常用DOS命o
diskcomp盘比较 append 讄非执行文件\?br />expand q原DOS文g fasthelp快速显C帮助信息?
fc 文g比较 interink启动服务?
setver 讄版本 intersvr启动客户机?
subst 路径替换 qbasic Basic集成环境
vsafe 防病毒 ?unformat恢复已格式化的磁盘?
ver 昄DOS版本号 ?smartdrv讄盘加速器
vol 昄盘h号 ?lh 程序装入高端内存 ?
ctty 改变控制讑֤ emm386 扩展内存理
常用命o具体介绍:
一、Dir
昄目录文g和子目录列表Q呵呵,q个当然是h知道的?
可以使用通配W(? ?*Q,Q表通配一个字W,*表通配L字符
*.后缀
指定要查看后~的文件?上面其实也可以ؓ?. 后缀?例如dir *.exe {于dir .exe
/p
每次昄一个列表屏q。要查看下一屏,h键盘上的L键?
/w
以宽格式昄列表Q在每一行上最多显C?5 个文件名或目录名?
/s
列出指定目录及所有子目录中出现的每个指定的文件名。比win环境下的查找快多?
dir *.* -> a.txt 把当前目录文件列表写入a.txt
dir *.* /s -> a.txt 把当前目录文件列表写入a.txtQ包括子目录下文件?
二、Attrib
昄、设|或删除指派l文件或目录的只诅R存、系l以及隐藏属性。如果在不含参数的情况下使用Q则 attrib 会显C当前目录中所有文件的属性?
+r
讄只读属性?
-r
清除只读属性?
+a
讄存文g属性?
-a
清除存档文g属性?
+s
讄pȝ属性?
-s
清除pȝ属性?
+h
讄隐藏属性?
-h
清除隐藏属性?
三、Cls
清除昄在命令提C符H口中的所有信息,q返回空H口Q即“清屏?
四、Exit
退出当前命令解释程序ƈq回到系l?
五、format
格式?
/q
执行快速格式化。删除以前已格式化卷的文件表和根目录Q但不在扇区之间扫描损坏区域。?/q 命o行选项应该仅格式化以前已格式化的完好的南?
六、Ipconfig
昄所有当前的 TCP/IP |络配置倹{刷新动态主机配|协?(DHCP) 和域名系l?(DNS) 讄。用不带参数的 ipconfig 可以昄所有适配器的 IP 地址、子|掩码、默认网兟?
/all
昄所有适配器的完整 TCP/IP 配置信息?
ipconfig {h?winipcfgQ后者在ME?8 ?95 上可用。尽?Windows XP 没有提供?winipcfg 命o一L囑Ş化界面,但可以用“网l连接”查看和更新 IP 地址。要做到q一点,h开 |络q接Q右键单L一|络q接Q单几Z状态”,然后单击“支持”选项卡?
该命令最适用于配|ؓ自动获取 IP 地址的计机。它使用户可以确定哪?TCP/IP 配置值是?DHCP、自动专?IP 地址 (APIPA) 和其他配|配|的?
七、md
创徏目录或子目录
八、Move
一个或多个文g从一个目录移动到指定的目录?
九、Nbtstat
昄本地计算机和q程计算机的Z TCP/IP (NetBT) 协议?NetBIOS l计资料、NetBIOS 名称表和 NetBIOS 名称~存。Nbtstat 可以h NetBIOS 名称~存和注册的 Windows Internet 名称服务 (WINS) 名称。用不带参数的 nbtstat 昄帮助。Nbtstat 命o行参数区分大写?
-a remotename
昄q程计算机的 NetBIOS 名称表,其中QRemoteName 是远E计机?NetBIOS 计算机名U?
-A IPAddress
昄q程计算机的 NetBIOS 名称表,其名U由q程计算机的 IP 地址指定Q以数点分隔)?
十、Netstat
昄zd?TCP q接、计机侦听的端口、以太网l计信息、IP 路由表、IPv4 l计信息Q对?IP、ICMP、TCP ?UDP 协议Q以?IPv6 l计信息Q对?IPv6、ICMPv6、通过 IPv6 ?TCP 以及通过 IPv6 ?UDP 协议Q。用时如果不带参数Qnetstat 昄zd?TCP q接?
-a
昄所有活动的 TCP q接以及计算Z听的 TCP ?UDP 端口?
十一、Ping
通过发送“网际消息控制协?(ICMP)”回响请求消息来验证与另一?TCP/IP 计算机的 IP U连接。回响应{消息的接收?/font>
况将和往q过E的ơ数一hC出来。Ping 是用于检网l连接性、可到达性和名称解析的疑N题的主要 TCP/IP 命o。如果不带参敎ͼping 显C帮助。名U和Ip地址解析是它的最单应用也是用的最多的?
-t
指定在中断前 ping 可以持箋发送回响请求信息到目的地。要中断q显C统计信息,h CTRL-BREAK。要中断q?pingQ请?CTRL-C?
-lSize
指定发送的回响h消息中“数据”字D늚长度Q以字节表示Q。默认gؓ 32。size 的最大值是 65,527?
十二、Rename (Ren)
更改文g的名U?
例如 ren *.abc *.cba
十三、Set
昄、设|或删除环境变量。如果没有Q何参敎ͼset 命o显C当前环境设|?
十四、Shutdown
允许您关闭或重新启动本地或远E计机。如果没有用参敎ͼshutdown 注销当前用户?
-m ComputerName
指定要关闭的计算机?
-t xx
用于系l关闭的定时器设|ؓ xx U。默认值是 20 U?
-l
注销当前用户Q这是默认设|?m ComputerName 优先?
-s
关闭本地计算机?
-r
关闭之后重新启动?
-a
中止关闭。除?-l ?ComputerName 外,pȝ忽略其它参数。在时期间Q您只可以?-a?
十五、System File Checker (sfc)
win下才有,在重新启动计机后扫描和验证所有受保护的系l文件?
/scannow
立即扫描所有受保护的系l文件?
/scanonce
一ơ扫描所有受保护的系l文件?
/purgecache
立即清除“Windows 文g保护”文仉速缓存,q扫描所有受保护的系l文件?
/cachesize=x
讄“Windows 文g保护”文仉速缓存的大小Q以 MB 为单位?
十六、type
昄文本文g的内宏V?type 命o查看文本文g或者是bat文g而不修改文g
十七、Tree
囑փ化显C\径或驱动器中盘的目录结构?
十八、Xcopy
复制文g和目录,包括子目录?
/s
复制非空的目录和子目录。如果省?/sQxcopy 在一个目录中工作?
/e
复制所有子目录Q包括空目录?
十九、copy
一个或多个文g从一个位|复制到其他位置
二十、del
删除指定文g?
ftp和bat批命令和net和telnet׃子命令太多,q里不说了,不过q几个都是常用到的?/font>
2 . echo content > fileName