Java提供了实现常见数据结构的类,创建链表等数据结构和创建数组一样简单,不再需要你去写具体的算法。
需要再更新。。。
12.1链表
12.2 堆栈
12.3 树集
12.4 散列表
12.5 向量
12.1 链表
如果需要处理一些类型相同的数据,人们习惯上使用数组这种数据结构,但数组在使用之前必须定义大小,而且不能动态定义大小。
链表是由若干个称作节点的对象组成的一种数据结构,分为两种类型:
单链表:每个节点含有一个数据和下一个节点对象的引用;
双链表:含有一个数据并含有上一个节点对象的引用和下一个节点对象的引用。
单链表示意图
双链表示意图
1 .创建链表
使用java.util 包中的LinkedList类创建一个链表。
例如,
LinkedList mylist=new LinkedList(); //创建了一个空双链表
//增加节点
mylist.add(“It”);
mylist.add(“is”);
mylist.add(“a”);
mylist.add(“door”);
这时,就形成了下图示意的链表,4个节点是自动连接在一起的。
is
0xAb9
0xbc
It
0x2b
null
a
0xbb9
Ox56
用LinkedList创建的一个链表
door
null
0xb6
mylist可以使用方法public Object get(index i)获取第i个节点中存储的数据。
存放在节点中的数据都被看作是一个Object对象。
下面的例子构造一个含有4个节点链表,并输出节点中的数据。
例子1
import java.util.*;
public class LinkListOne
{public static void main(String args[])
{ LinkedList mylist=new LinkedList();
mylist.add("It"); //链表中的第一个节点。
mylist.add("is"); //链表中的第二个节点。
mylist.add("a"); //链表中的第三个节点。
mylist.add("door"); //链表中的第四个节点。
int number=mylist.size(); //获取链表的长度。
for(int i=0;i {String temp=(String)mylist.get(i);
System.out.println("第"+i+"节点中的数据:"+temp);
}
}
}
注:由于任何类都是Object类的子类,因此可以把任何一个对象作为链表的节点对象。
需要注意的是当使用get()获取一个节点对象后,要用类型转换运算符转化回原来的类型。
2.LinkedList类中的常用方法:
boolean add(Object element) :向链表的末尾填加一个新的节点对象elememt。
void add(int index ,Object element) :向链表的指定位置尾填加一个新的节点
对象elememt。
void addFirst(Object element) :把节点对象elememt填加到链表的表头。
void addLast(Object element) :把节点对象elememt填加到链表的末尾。
void clear():删除链表的所有节点对象。
Object remove(int index):删除指定位置上的节点对象。
boolean remove(Object element):将首次出现的节点对象element删除。
Obiect removeFirst():删除第一个节点对象,并返回这个节点对象。
Obiect removeLast():删除最后一个节点对象。
Object get(int index):得到链表中指定位置处的节点对象。
Object getFirst():得到链表中第一个节点对象。
Object getLast():得到链表中最后一个节点对象。
int indexOf(Object element):返回节点对象element在链表中首次出现的位置,
如果链表中无此节点对象则返回-1。
public int lastIndexOf(Object element):返回节点对象element在链表中最后出现的位
置,如果链表中无此节点对象则返回-1。
public Object set(int index ,Object element):用节点对象element替换链表中指定位置
处的节点对象。并返回链表中先前位置处的节点对象。
public int size():返回链表的长度,即节点的个数。
public boolean contains(Object element):判断链表节点对象中是否含有element。
下面的例子2中包含了LinkedList类中的一些常用方法。
例子2
import java.util.*;
public class LinkListTwo
{public static void main(String args[])
{ LinkedList mylist=new LinkedList();
mylist.add("is");
mylist.add("a");
int number=mylist.size();
System.out.println("现在链表中有"+number+"个节点:");
for(int i=0;i {String temp=(String)mylist.get(i);
System.out.println("第"+i+"节点中的数据:"+temp);
}
mylist.addFirst("It");
mylist.addLast("door");
number=mylist.size();
System.out.println("现在链表中有"+number+"个节点:");
for(int i=0;i {String temp=(String)mylist.get(i);
System.out.println("第"+i+"节点中的数据:"+temp);
}
mylist.remove(0);
mylist.remove(1);
mylist.set(0,"open");
number=mylist.size();
System.out.println("现在链表中有"+number+"个节点:");
for(int i=0;i {String temp=(String)mylist.get(i);
System.out.println("第"+i+"节点中的数据:"+temp);
}
}
}
3.使用Iterator类遍历链表
在例子1和例子2中我们借助get方法实现了遍历链表。
我们可以借助Iterator对象实现遍历链表,
一个链表对象可以使用iterator()方法获取一个Iterator对象,
后者使用next()方法遍历链表。
例子3,我们把学生的成绩存放在一个链表中,并实现了遍历链表。
import java.util.*;
class Student
{String name ;int number;float score;
Student(String name,int number,float score)
{this.name=name;this.number=number;this.score=score;
}
}
public class LinkListThree
{public static void main(String args[])
{ LinkedList mylist=new LinkedList();
Student stu_1=new Student("赵好民" ,9012,80.0f),
stu_2=new Student("钱小青" ,9013,90.0f),
stu_3=new Student("孙力枚" ,9014,78.0f),
stu_4=new Student("周左右" ,9015,55.0f);
mylist.add(stu_1); mylist.add(stu_2);
mylist.add(stu_3); mylist.add(stu_4);
Iterator iter=mylist.iterator();
while(iter.hasNext()){
Student te=(Student)iter.next();
System.out.println(te.name+" "+te.number+" "+te.score);
}
}
}
下面是一个较复杂的例子,用链表来管理商品的库存情况。
通过节点存放一个商品对象,该对象具有代号、名称、库存量和单价等属性。
例子4
import java.util.*;import java.awt.event.*;import java.awt.*;
import javax.swing.*;import java.io.*;
class 商品 extends Panel
{String 代号,名称;int 库存;float 单价;
商品(String 代号,String 名称,int 库存,float 单价)
{this.代号=代号;this.名称=名称;this.库存=库存;this.单价=单价;
}
}
class ShowWin extends JFrame implements ActionListener
{
LinkedList goods_list=null;
JTextField 代号文本框=new JTextField(),
名称文本框=new JTextField(),
库存文本框=new JTextField(),
单价文本框=new JTextField(),
删除文本框=new JTextField();
JButton b_add=new JButton("添加商品"),
b_del=new JButton("删除商品"),
b_show =new JButton("显示商品清单");
JTextArea 显示区=new JTextArea();
ShowWin()
{goods_list=new LinkedList();
Container con=getContentPane();
JScrollPane pane=new JScrollPane(显示区);
显示区.setEditable(false);
JPanel save=new JPanel();
save.setLayout(new GridLayout(5,2));
save.add(new Label("输入代号:"));save.add(代号文本框);
save.add(new Label("输入名称:"));save.add(名称文本框);
save.add(new Label("输入库存:"));save.add(库存文本框);
save.add(new Label("输入单价:"));save.add(单价文本框);
save.add(new Label("点击添加:"));save.add(b_add);
JPanel del=new JPanel();del.setLayout(new GridLayout(2,2));
del.add(new Label("输入删除的代号:"));del.add(删除文本框);
del.add(new Label("点击删除:"));del.add(b_del);
JPanel show=new JPanel();show.setLayout(new BorderLayout());
show.add(pane,BorderLayout.CENTER);show.add(b_show,BorderLayout.SOUTH);
JSplitPane split_one,split_two;
split_one=new JSplitPane(JSplitPane.VERTICAL_SPLIT,save,del);
split_two=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,true,split_one,show);
con.add(split_two,BorderLayout.CENTER);
b_add.addActionListener(this);b_del.addActionListener(this);
b_show.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==b_add){
String daihao=null,mingcheng=null;
int kucun=0;
float danjia=0.0f;
daihao=代号文本框.getText();
mingcheng=名称文本框.getText();
kucun=Integer.parseInt(库存文本框.getText());
danjia=Float.valueOf(单价文本框.getText()).floatValue();
商品 goods=new 商品(daihao,mingcheng,kucun,danjia);
goods_list.add(goods);
try {
FileOutputStream file=new FileOutputStream("goods.txt");
ObjectOutputStream out=new ObjectOutputStream(file);
out.writeObject(goods_list);
out.close();
}catch(IOException event){}
}
else if(e.getSource()==b_del) {
String daihao=删除文本框.getText();
try {
FileInputStream come_in=new FileInputStream("goods.txt");
ObjectInputStream in=new ObjectInputStream(come_in);
goods_list=(LinkedList)in.readObject();
in.close();
}catch(ClassNotFoundException event){}
catch(IOException event){}
int number=goods_list.size();
for(int i=0;i {商品 temp=(商品)goods_list.get(i);
if(temp.代号.equals(daihao)) {
goods_list.remove(i);
}
try{
FileOutputStream file=new FileOutputStream("goods.txt");
ObjectOutputStream out=new ObjectOutputStream(file);
out.writeObject(goods_list);
out.close();
}
catch(IOException event){}
}
}
else if(e.getSource()==b_show)
{ 显示区.setText(null);
try {
FileInputStream come_in=new FileInputStream("goods.txt");
ObjectInputStream in=new ObjectInputStream(come_in);
goods_list=(LinkedList)in.readObject();
}
catch(ClassNotFoundException event){}
catch(IOException event){}
Iterator iter=goods_list.iterator();
while(iter.hasNext())
{ 商品 te=(商品)iter.next();
显示区.append("商品代号:"+te.代号+" ");
显示区.append("商品名称:"+te.名称+" ");
显示区.append("商品库存:"+te.库存+" ");
显示区.append("商品单价:"+te.单价+" ");
显示区.append("\n");
}
}
}
}
public class LinkListFour
{public static void main(String args[])
{ ShowWin win=new ShowWin();
win.setSize(100,100);
win.setVisible(true);
win.addWindowListener(new WindowAdapter()
{public void windowClosing(WindowEvent e)
{System.exit(0);}});
}
}
注:在上面的例子中,商品类故意扩展了java.awt包中的Panel,
因为Java提供给我们的绝大多数对象都是所谓序列化的,
比如组件等,这是为了保证把对象写入到文件中后,
能再把对象正确读回到程序中的缘故。
商品类是我们自己写的的类,没有序列化,只要随便扩展一个序列化的类即可。
12.2 堆栈
堆栈是一种“后进先出”的数据结构,只能在一端进行输入或输出数据的操作。堆栈把第一个放入该堆栈的数据放在最底下,而把后续放入的数据放在已有数据的顶上,如图所示。
数据
数据
数据
数据
新数据
输出数据
压栈
弹栈
堆栈结构示意图
向堆栈中输入数据的操作称为“压栈”,从栈中输出数据的操作称为“弹栈”。
使用java.util包中的Stack类创建一个堆栈对象,堆栈对象可以使用
Object push(Object data);输入数据,实现压栈操作.
Object pop();输出数据,实现弹栈操作。
boolean empty();判断堆栈是否还有数据,有数据返回false ,否则返回true。
Object peek();查看堆栈顶端的数据,但不删除该数据。
public int search(Object data);获取数据在堆栈中的位置,最顶端的位置是1,向下依次增加,如果堆栈不含此数据,则返回-1。
注:由于任何类都是Object类的子类,因此可以把任何一个对象压入堆栈。
下面的例子5将数字1,2,3,4,5,6压入堆栈,然后弹出。
例子5
import java.util.*;
class StackOne
{public static void main(String args[])
{Stack mystack=new Stack();
mystack.push(new Integer(1)); mystack.push(new Integer(2));
mystack.push(new Integer(3)); mystack.push(new Integer(4));
mystack.push(new Integer(5)); mystack.push(new Integer(6));
while(!(mystack.empty()))
{Integer temp=(Integer)mystack.pop();
System.out.print(" "+temp.toString());}
}
}
堆栈是很灵活的数据结构,使用堆栈可以节省内存的开销。
比如,递归是一种很消耗内存的算法,我们可以借助堆栈消除大部分递归,
达到和递归算法同样的目的。
Fibonacii整数序列是我们熟悉的一个递归序列,
它的第n项是前两项的和,第一项和第二项是1。
下面的例子6用堆栈输出该递归序列的若干项。
import java.util.*;
class StackTwo
{public static void main(String args[])
{Stack mystack=new Stack();
mystack.push(new Integer(1));
mystack.push(new Integer(1));
int k=1;
while(k<=10)
for(int i=1;i<=2;i++){
Integer F1=(Integer)mystack.pop();
int f1=F1.intValue();
Integer F2=(Integer)mystack.pop();
int f2=F2.intValue();
Integer temp=new Integer(f1+f2);
System.out.println(""+temp.toString());
mystack.push(temp);
mystack.push(F2);
k++;
}
}
}
注:如果将上述程序中
mystack.push(temp);
mystack.push(F2);
两个语句的顺序颠倒,输出的结果如何?
12.3 树集
树集是有一些节点对象组成的数据结构,节点按着树形一层一层的排列,如下图所示。
节点
节点
节点
节点
节点
节点
节点
节点
节点
节点
树集结构示意图
1.用构造方法TreeSet()创建一个树集
可以使用java.util包中的TreeSet来创建一个树集,如
TreeSet mytree=new TreeSet();
mytree.add("boy"); //然后使用add方法为树集添加节点:
mytree.add("zoo");
mytree.add("apple");
mytree.add("girl");
和链表不同的是,当使用构造方法TreeSet()创建树集后,
再用add 方法增加节点时,
节点会按其存放的数据的字典序一层一层地依次排列,
在同一层中的节点从左到右按字典序递增排列,
下一层的都比上一层的小。Mytree的示意图如下图。
apple
boy节点
girl节点
zoo节点
用TreeSet构造的树集
两个字符串对象s1,s2可以使用
s1.compare(s2);
按字典序比较大小,即s1.compare(s2)=0时二者相同,
s1.compare(s2)>0时,称s1大于s2,s1.
compare(s2)<0时,称s1小于s2。
下面的例子使用构造方法TreeSet()创建了一个树集,并填加了4个节点。
例子7
import java.util.*;
class TreeOne
{public static void main(String args[])
{ TreeSet mytree=new TreeSet();
mytree.add("boy");
mytree.add("zoo");
mytree.add("apple");
mytree.add("girl");
Iterator te=mytree.iterator();
while(te.hasNext())
System.out.println(""+te.next());
}
}
输出结果是:
2.用构造方法TreeSet(Comparator c)创建一个树集
很多对象不适合用字典序进行比较,在创建树集时可自己规定节点按着什么样的“大小”顺序排列。
假如我们有四个学生对象,他们有姓名和成绩,
我们想把这四个对象做为一个树集的节点,并按着成绩的高低排列节点,而不是按着姓名的字典序排列节点。
· 首先创建学生的Student类必须实现接口:Comparable。
Comparable接口中有一个方法:
public int compareTo(Object b);
Student类通过实现这个接口来规定它创建的对象的大小关系,如下所示。
class Student implements Comparable{
int english=0;
String name;
Student(int e,String n){
english=e;
name=n;
}
public int compareTo(Object b){
Student st=(Student)b;
return (this.english-st.english); //按成绩大小排列对象。
}
}
Java规定:
a.compareTo(b)=0时,称二者相等;
s1.compare(s2)>0时,称a大于b;
s1.compare(s2)<0时,称a小于b。
然后用构造方法TreeSet(Comparator c)创建一个树集,通过参数c规定树集的节点按怎样的顺序排列:
TreeSet mytree=new TreeSet(new Comparator(){
public int compare(Object a,Object b){
Student stu1=(Student)a;
Student stu2=(Student)b;
return stu1.compareTo(stu2);
}});
注:Comparator是java.util包中的一个接口,compare是接口中的方法,因此必须给出方法体。
下面的例子8中的树集按着英语成绩从底到高存放四个Student对象。
import java.util.*;import java.awt.*;
class TreeTwo
{public static void main(String args[])
{
TreeSet mytree=new TreeSet(new Comparator(){
public int compare(Object a,Object b){
Student stu1=(Student)a;
Student stu2=(Student)b;
return stu1.compareTo(stu2);}
});
Student st1,st2,st3,st4;
st1=new Student(90,"zhan ying");st2=new Student(66,"wang heng");
st3=new Student(86,"Liuh qing");st4=new Student(76,"yage ming");
mytree.add(st1);mytree.add(st2);mytree.add(st3);mytree.add(st4);
Iterator te=mytree.iterator();
while(te.hasNext())
{Student stu=(Student)te.next();
System.out.println(""+stu.name+" "+stu.english);}
}
}
class Student implements Comparable {
int english=0;String name;
Student(int e,String n){
english=e;name=n;
}
public int compareTo(Object b)
{ Student st=(Student)b;
return (this.english-st.english);
}
}
输出结果是:
注:树集中不容许出现大小相等的两个节点,例如,在上述例子中如果再添加语句
st5=new Student(76,"keng wenyi"); mytree.add(st5);
是无效的。
如果允许成绩相同,可把上述例子中Student类中的compareTo方法更改为:
public int compareTo(Object b)
{ Student st=(Student)b;
if((this.english-st.English)==0)
return 1;
else
return (this.english-st.english);
}
注:理论上已经知道,把一个元素插入树集的合适位置要比插入数组或链表中的合适位置效率高。
3.TreeSet类的一些常用方法:
public boolean add(Object o):向树集添加加节点,添加成功返回true,否则返回false。
public void clear():删除所有的节点。
public void contains(Object o):如果包含节点o返回true 。
public Object first():返回根节点,即第一个节点(最小的节点)。
public Object last():返回最后一个节点(最大的节点)。
public isEmpty():判断是否是空树集,如果树集不含节点返回true 。
public boolean remove(Object o):删除节点o。
public int size():返回节点数目。
下面的例子用树集实现了某次演出的节目单的安排与管理,按演出时间的先后对节目单排序。
import java.util.*;import java.awt.event.*;
import java.awt.*;
class 节目 implements Comparable{
String name;double time;
节目(String 名称,double 演出时间)
{name=名称;time=演出时间;
}
public int compareTo(Object b)
{节目 item=(节目)b;
return (int)((this.time-item.time)*1000);
}
}
class Win extends Frame implements ActionListener
{ TreeSet 节目清单=null;
TextField 名称文本框=new TextField(10),
时间文本框=new TextField(5),
删除文本框=new TextField(5);
Button b_add=new Button("添加节目"),
b_del=new Button("删除节目"),
b_show =new Button("显示节目清单");
TextArea 显示区=new TextArea();
Win(){
节目清单=new TreeSet(new Comparator(){
public int compare(Object a,Object b){
节目 item_1=(节目)a;
节目 item_2=(节目)b;
return item_1.compareTo(item_2);
}
});
Panel 节目单输入区=new Panel();
节目单输入区.add(new Label("节目名称:"));
节目单输入区.add(名称文本框);
节目单输入区.add(new Label("演出时间:"));
节目单输入区.add(时间文本框);
节目单输入区.add(new Label("点击添加:"));
节目单输入区.add(b_add);
节目单输入区.add(b_show);
Panel 节目单删除区=new Panel();
节目单删除区.add(new Label("输入演出的时间:"));
节目单删除区.add(删除文本框);
节目单删除区.add(new Label("点击删除:"));
节目单删除区.add(b_del);
Panel 节目单显示区=new Panel();
节目单显示区.add(显示区);
显示区.setBackground(Color.pink);
b_add.addActionListener(this);b_del.addActionListener(this);
b_show.addActionListener(this);
add(节目单输入区,"North");add(节目单显示区,"Center");
add(节目单删除区,"South");
}
public void actionPerformed(ActionEvent e)
{if(e.getSource()==b_add)
{ String 名称=null;
double 时间=0.0;
名称=名称文本框.getText();
try{时间=Double.valueOf(时间文本框.getText()).doubleValue();
}
catch(NumberFormatException ee)
{时间文本框.setText("请输入代表时间的实数");
}
节目 programme=new 节目(名称,时间);
节目清单.add(programme);
showing();
}
else if(e.getSource()==b_del)
{节目 待删除节目=null;
double time=Double.valueOf(删除文本框.getText()).doubleValue();
Iterator te=节目清单.iterator();
while(te.hasNext())
{节目 item=(节目)te.next();
if(Math.abs(item.time-time)<=0.000001d)
{待删除节目=item; }
}
if(待删除节目!=null) 节目清单.remove(待删除节目);
showing();
}
else if(e.getSource()==b_show)
{ showing();
}
}
void showing()
{ 显示区.setText(null);
Iterator iter=节目清单.iterator();
while(iter.hasNext())
{节目 item=(节目)iter.next();
显示区.append("节目名称:"+item.name+"演出时间: "+item.time);
显示区.append("\n");
}
}
}
public class Tree_3
{public static void main(String args[])
{ Win win=new Win();
win.setSize(500,250);win.setVisible(true);
win.addWindowListener(new WindowAdapter()
{public void windowClosing(WindowEvent e)
{System.exit(0);}});
}
}
12.4 散列表 Hashtable
散列表是使用相关关键字查找被存储的数据项的一种数据结构,关键字必须唯一。
散列表在它需要更多的存储空间时会自动增大容量。
例如,如果散列表的装载因子是0.75,那么当散列表的容量被使用了75%时,它就把容量增加到原始容量的2倍。
对于数组和链表这两种数据结构,采用匹配查找法效率不高。
使用java.util包中的Hashtable类来创建散列表对象,
该类的常用方法如下:
public Hashtable():创建具有默认容量和装载因子为0.75的散列表。
public Hashtable(int itialCapacity):创建具有指定容量和装载因子为0.75的散列表。
public Hashtable(int initialCapacity,float loadFactor):创建具有默认容量和指定装载因子散列表。
public void clear():清空散列表。
public boolean contains(Object o):判断散列表是否有含有元素o。
public Object get(Object key):获取散列表中具有关键字key的数据项。
public boolean isEmpty():判断散列表是否为空。
public Object put(Object key,Object value):向散列表添加数据项value并把关键字key关联到数据项value。
public Object remove(Object key):删除关键字是key的数据项。
public int size():获取散列表中关键字的数目。
elements()方法返回一个Enumeration对象,实现遍历散列表。
下面的例子10使用Hashtable()创建一个散列表,存放Student对象,
每个Student对象用该对象的学号作为关键字。
例子10
import java.util.*;
class Student{
int english=0;
String name,number;
Student(String na,String nu,int e){
english=e;
name=na;
number =nu;
}
}
public class HT{
public static void main(String args[]){
Hashtable hashtable=new Hashtable();
hashtable.put("199901",new Student("199901","王小林",98));
hashtable.put("199902",new Student("199902","能林茂",70));
hashtable.put("199903",new Student("199903","多种林",93));
hashtable.put("199904",new Student("199904","围林蛤",46));
hashtable.put("199905",new Student("199905","夹贸林",77));
hashtable.put("199906",new Student("199906","噔林可",55));
hashtable.put("199907",new Student("199907","降王林",68));
hashtable.put("199908",new Student("199908","纠林咯",76));
Student stu=(Student)hashtable.get("199902"); //检索一个元素。
System.out.println(stu.number+" "+stu.name+" "+stu.english);
hashtable.remove("199906"); //删除一个元素
System.out.println("散列表中现在含有:"+hashtable.size()+"个元素");
Enumeration enum=hashtable.elements();
while(enum.hasMoreElements()) //遍历当前散列表。
{Student s=(Student)enum.nextElement();
System.out.println(s.number+" "+s.name+" "+s.english);
}
}
}
下面的例子11使用散列表实现学生成绩单的输入和查询。
import java.util.*;import java.awt.event.*;import java.awt.*;
import javax.swing.*;import java.io.*;
class 学生 extends JPanel
{String 学号,姓名;float 分数;
学生(String 学号,String 姓名,float 分数)
{this.学号=学号;this.姓名=姓名;this.分数=分数;
}
}
class ShowWin extends JFrame implements ActionListener
{
Hashtable hashtable=new Hashtable();
JTextField 学号文本框=new JTextField(),
姓名文本框=new JTextField(),
分数文本框=new JTextField(),
查询文本框=new JTextField();
JButton b_add=new JButton("添加成绩"),
b_show =new JButton("显示成绩");
JTextField 成绩显示条=new JTextField();
ShowWin()
{Container con=getContentPane();
JPanel 成绩输入区=new JPanel();
成绩输入区.setLayout(new GridLayout(5,2));
成绩输入区.add(new Label("成绩输入区:"));
成绩输入区.add(new Label());
成绩输入区.add(new Label("考生学号:"));
成绩输入区.add(学号文本框);
成绩输入区.add(new JLabel("考生姓名:"));
成绩输入区.add(姓名文本框);
成绩输入区.add(new Label("考生成绩:"));
成绩输入区.add(分数文本框);
成绩输入区.add(new Label("点击添加:"));
成绩输入区.add(b_add);
JPanel 查询显示区=new JPanel();
查询显示区.setLayout(new GridLayout(3,2));
查询显示区.add(new Label("成绩查询区:"));
查询显示区.add(new Label());
查询显示区.add(new Label("输入考生的学号:"));
查询显示区.add(查询文本框);
查询显示区.add(b_show);
查询显示区.add(成绩显示条);
JSplitPane split;
split=new JSplitPane(JSplitPane.VERTICAL_SPLIT,成绩输入区,查询显示区);
con.add(split,BorderLayout.CENTER);
con.add(new Label("成绩输入和查询系统"),BorderLayout.NORTH);
b_add.addActionListener(this);b_show.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{if(e.getSource()==b_add)
{String 学号=null,姓名=null;float 分数=0.0f;
try {学号=学号文本框.getText();
姓名=姓名文本框.getText();
}
catch(NullPointerException ee)
{ 学号文本框.setText("请输入学号");
姓名文本框.setText("请输入姓名");
}
try{分数=Float.valueOf(分数文本框.getText()).floatValue();}
catch(NumberFormatException ee)
{分数文本框.setText("请输入数字字符");}
学生 stu=new 学生(学号,姓名,分数);
hashtable.put(学号,stu);
try {FileOutputStream file=new FileOutputStream("score.txt");
ObjectOutputStream out=new ObjectOutputStream(file);
out.writeObject(hashtable);
out.close();
}
catch(IOException event){}
}
else if(e.getSource()==b_show)
{ String temp=null;
temp=查询文本框.getText();
成绩显示条.setText(null);
try {FileInputStream come_in=new FileInputStream("score.txt");
ObjectInputStream in=new ObjectInputStream(come_in);
hashtable=(Hashtable)in.readObject();
in.close();
}catch(ClassNotFoundException event){}
catch(IOException event){System.out.println("文件无法读出");}
学生 s=(学生)hashtable.get(temp);
成绩显示条.setText("姓名:"+s.姓名+"学号:"+s.学号+"成绩:"+s.分数);
}
}
}
public class HT_2
{public static void main(String args[])
{ ShowWin win=new ShowWin();
win.setSize(100,100); win.setVisible(true);
win.addWindowListener(new WindowAdapter()
{public void windowClosing(WindowEvent e)
{System.exit(0);}});
}
}
// Fig. 21.3: WordTypeCount.java
// Count the number of occurrences of each word in a string.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class WordTypeCount extends JFrame {
private JTextArea inputField;
private JLabel prompt;
private JTextArea display;
private JButton goButton;
private Hashtable table;
public WordTypeCount()
{
super( "Word Type Count" );
inputField = new JTextArea( 3, 20 );
table = new Hashtable();
goButton = new JButton( "Go" );
goButton.addActionListener(
new ActionListener() { // anonymous inner class
public void actionPerformed( ActionEvent event )
{
createTable();
display.setText( createOutput() );
}
} // end anonymous inner class
); // end call to addActionListener
prompt = new JLabel( "Enter a string:" );
display = new JTextArea( 15, 20 );
display.setEditable( false );
JScrollPane displayScrollPane = new JScrollPane( display );
// add components to GUI
Container container = getContentPane();
container.setLayout( new FlowLayout() );
container.add( prompt );
container.add( inputField );
container.add( goButton );
container.add( displayScrollPane );
setSize( 400, 400 );
setVisible( true );
} // end constructor
// create table from user input
private void createTable() {
String input = inputField.getText();
StringTokenizer words = new StringTokenizer( input, " \n\t\r" );
while ( words.hasMoreTokens() ) {
String word = words.nextToken().toLowerCase(); // get word
// if the table contains the word
if ( table.containsKey( word ) ) {
Integer count = (Integer) table.get( word ); // get value
// and increment it
table.put( word, new Integer( count.intValue() + 1 ) );
}
else // otherwise add the word with a value of 1
table.put( word, new Integer( 1 ) );
} // end while
} // end method createTable
// create string containing table values
private String createOutput() {
String output = "";
Enumeration keys = table.keys();
// iterate through the keys
while ( keys.hasMoreElements() ) {
Object currentKey = keys.nextElement();
// output the key-value pairs
output += currentKey + "\t" + table.get( currentKey ) + "\n";
}
output += "size: " + table.size() + "\n";
output += "isEmpty: " + table.isEmpty() + "\n";
return output;
} // end method createOutput
public static void main( String args[] )
{
WordTypeCount application = new WordTypeCount();
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
} // end class WordTypeCount
&S226; Map
– Associates keys to values
– Cannot contain duplicate keys
&S226; Called one-to-one mapping
// Fig. 22.14: WordTypeCount.java
// Program counts the number of occurrences of each word in a string
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class WordTypeCount extends JFrame {
private JTextArea inputField;
private JLabel prompt;
private JTextArea display;
private JButton goButton;
private Map map;
public WordTypeCount()
{
super( "Word Type Count" );
inputField = new JTextArea( 3, 20 );
map = new HashMap();
goButton = new JButton( "Go" );
goButton.addActionListener(
new ActionListener() { // inner class
public void actionPerformed( ActionEvent event )
{
createMap();
display.setText( createOutput() );
}
} // end inner class
); // end call to addActionListener
prompt = new JLabel( "Enter a string:" );
display = new JTextArea( 15, 20 );
display.setEditable( false );
JScrollPane displayScrollPane = new JScrollPane( display );
// add components to GUI
Container container = getContentPane();
container.setLayout( new FlowLayout() );
container.add( prompt );
container.add( inputField );
container.add( goButton );
container.add( displayScrollPane );
setSize( 400, 400 );
show();
} // end constructor
// create map from user input
private void createMap()
{
String input = inputField.getText();
StringTokenizer tokenizer = new StringTokenizer( input );
while ( tokenizer.hasMoreTokens() ) {
String word = tokenizer.nextToken().toLowerCase(); // get word
// if the map contains the word
if ( map.containsKey( word ) ) {
Integer count = (Integer) map.get( word ); // get value
// increment value
map.put( word, new Integer( count.intValue() + 1 ) );
}
else // otherwise add word with a value of 1 to map
map.put( word, new Integer( 1 ) );
} // end while
} // end method createMap
// create string containing map values
private String createOutput() {
StringBuffer output = new StringBuffer( "" );
Iterator keys = map.keySet().iterator();
// iterate through the keys
while ( keys.hasNext() ) {
Object currentKey = keys.next();
// output the key-value pairs
output.append( currentKey + "\t" +
map.get( currentKey ) + "\n" );
}
output.append( "size: " + map.size() + "\n" );
output.append( "isEmpty: " + map.isEmpty() + "\n" );
return output.toString();
} // end method createOutput
public static void main( String args[] )
{
WordTypeCount application = new WordTypeCount();
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
} // end class WordTypeCount
12.5 向量
Java的java.util包中的Vector类负责创建一个向量对象。
向量相当于动态的,可以存储不同数据类型数据的数组。
向量的大小会自动的增加。
注意:当你把某一种类型的对象放入一个向量后,数据被默认为是Object对象,因此当向量中取出一个元素时应用强制类型转化运算符转化为原来的类型。
Vector类的常用方法:
void add(Object o):将对象o添加到向量的末尾。
void add(int index Object o):将对象o插入到向量的指定位置。
void addElements(Object o):将对象o添加到向量的末尾。
boolean contains(Object o):判断对象o是否为向量的成员。
Object elementAt(int index):获取指定位置处的成员。
Object get(int index):获取此向量指定位置处的成员。
Object firstElement(): 获取此向量的第一个成员。
Object lastElement(): 获取此向量的最后一个成员。
int indexOf(Obkect o):获取对象o在此向量中首次出现的位置。
int indexOf(Obkect o,int index):从指定位置查找对象o在此向量中首次现的位置。
int lastIndexOf(Object o): 获取对象o在此向量中最后出现的位置。
int lastIndexOf(Object o,int index):对象o在此向量位置index之前最后出现的位
置。
Object remove(int index):从此向量中删除指定位置处的成员,并返回这个成员。
void removeAllElements():删除向量的所有成员。
boolean removeElement(Object o):删除第一次出现的成员o。
boolean removeElementAt(int index):删除指定位置处的成员。
void set(int index,Object o):把指定位置处的成员用o替换掉。
void setElementAt(Object o,int index):把指定位置处的成员用o替换掉。
Enumeration elements():获取一个枚举对象。
在下面的例子中将几个不同的对象添加到向量。
import java.util.*;
class Example26_12
{public static void main(String args[])
{ Vector vector=new Vector(); Date date=new Date();
vector.add(new Integer(1));vector.add(new Float(3.45f));
vector.add(new Double(7.75));vector.add(new Boolean(true));
vector.add(date);
System.out.println(vector.size());
Integer number1=(Integer)vector.get(0);
System.out.println("向量的第1个元素: "+number1.intValue());
Float number2=(Float)vector.get(1);
System.out.println("向量的第2个元素: "+number2.floatValue());
Double number3=(Double)vector.get(2);
System.out.println("向量的第3个元素: "+number3.doubleValue());
Boolean number4=(Boolean)vector.get(3);
System.out.println("向量的第4个元素: "+number4.booleanValue());
date=(Date)vector.lastElement();
System.out.println("向量的第5个元素: "+date.toString());
if(vector.contains(date))
System.out.println("ok");
}
}
下面的例子使用向量技术,用鼠标自由作画。
每当拖动鼠标时,我们把获得的鼠标位置坐标存入一个向量,然后依次把向量的点连成直线。
例子13
import java.applet.*;
import java.awt.*;import java.util.*;
import java.awt.event.*;
class Point
{int x,y;
Point(int x,int y)
{this.x=x;this.y=y;
}
}
public class extends Applet implements MouseMotionListener,MouseListener
{ int x=-1,y=-1;
Vector v=null;int n=1;
public void init()
{ setBackground(Color.green);
addMouseMotionListener(this);
addMouseListener(this);
v=new Vector();
}
public void paint(Graphics g){
if(x!=-1&&y!=-1){
n=v.size();
for(int i=0;i Point p1=(Point)v.elementAt(i);
Point p2=(Point)v.elementAt(i+1);
g.drawLine(p1.x,p1.y,p2.x,p2.y);
}
}
}
public void mouseDragged(MouseEvent e)
{ x=(int)e.getX();
y=(int)e.getY();
Point p=new Point(x,y);
v.addElement(p);
repaint();
}
public void mouseMoved(MouseEvent e) {}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){
v.removeAllElements();
}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e){}
public void update(Graphics g)
{ paint(g);
}
}
– &S226;Properties : Persistent Hashtable
&S226; Can be written to output stream
&S226; Can be read from input stream
– Provides methods setProperty and getProperty
&S226; Store/obtain key-value pairs of Strings
// Fig. 21.4: PropertiesTest.java
// Demonstrates class Properties of the java.util package.
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
public class PropertiesTest extends JFrame {
private JLabel statusLabel;
private Properties table;
private JTextArea displayArea;
private JTextField valueField, nameField;
// set up GUI to test Properties table
public PropertiesTest()
{
super( "Properties Test" );
table = new Properties(); // create Properties table
Container container = getContentPane();
// set up NORTH of window's BorderLayout
JPanel northSubPanel = new JPanel();
northSubPanel.add( new JLabel( "Property value" ) );
valueField = new JTextField( 10 );
northSubPanel.add( valueField );
northSubPanel.add( new JLabel( "Property name (key)" ) );
nameField = new JTextField( 10 );
northSubPanel.add( nameField );
JPanel northPanel = new JPanel();
northPanel.setLayout( new BorderLayout() );
northPanel.add( northSubPanel, BorderLayout.NORTH );
statusLabel = new JLabel();
northPanel.add( statusLabel, BorderLayout.SOUTH );
container.add( northPanel, BorderLayout.NORTH );
// set up CENTER of window's BorderLayout
displayArea = new JTextArea( 4, 35 );
container.add( new JScrollPane( displayArea ),
BorderLayout.CENTER );
// set up SOUTH of window's BorderLayout
JPanel southPanel = new JPanel();
southPanel.setLayout( new GridLayout( 1, 5 ) );
// button to put a name-value pair in Properties table
JButton putButton = new JButton( "Put" );
southPanel.add( putButton );
putButton.addActionListener(
new ActionListener() { // anonymous inner class
// put name-value pair in Properties table
public void actionPerformed( ActionEvent event )
{
Object value = table.setProperty(
nameField.getText(), valueField.getText() );
if ( value == null )
showstatus( "Put: " + nameField.getText() +" " + valueField.getText() );
else
showstatus( "Put: " + nameField.getText() + " " + valueField.getText() + "; Replaced: " + value );
listProperties();
}
} // end anonymous inner class
); // end call to addActionListener
// button to empty contents of Properties table
JButton clearButton = new JButton( "Clear" );
southPanel.add( clearButton );
clearButton.addActionListener(
new ActionListener() { // anonymous inner class
// use method clear to empty table
public void actionPerformed( ActionEvent event )
{
table.clear();
showstatus( "Table in memory cleared" );
listProperties();
}
} // end anonymous inner class
); // end call to addActionListener
// button to get value of a property
JButton getPropertyButton = new JButton( "Get property" );
southPanel.add( getPropertyButton );
getPropertyButton.addActionListener(
new ActionListener() { // anonymous inner class
// use method getProperty to obtain a property value
public void actionPerformed( ActionEvent event )
{
Object value = table.getProperty(
nameField.getText() );
if ( value != null )
showstatus( "Get property: " + nameField.getText() +
" " + value.toString() );
else
showstatus( "Get: " + nameField.getText() +
" not in table" );
listProperties();
}
} // end anonymous inner class
); // end call to addActionListener
// button to save contents of Properties table to file
JButton saveButton = new JButton( "Save" );
southPanel.add( saveButton );
saveButton.addActionListener(
new ActionListener() { // anonymous inner class
// use method save to place contents in file
public void actionPerformed( ActionEvent event )
{
// save contents of table
try {
FileOutputStream output =
new FileOutputStream( "props.dat" );
table.store( output, "Sample Properties" );
output.close();
listProperties();
}
// process problems with file output
catch( IOException ioException ) {
ioException.printStackTrace();
}
}
} // end anonymous inner class
); // end call to addActionListener
// button to load contents of Properties table from file
JButton loadButton = new JButton( "Load" );
southPanel.add( loadButton );
loadButton.addActionListener(
new ActionListener() { // anonymous inner class
// use method load to read contents from file
public void actionPerformed( ActionEvent event )
{
// load contents of table
try {
FileInputStream input =
new FileInputStream( "props.dat" );
table.load( input );
input.close();
listProperties();
}
// process problems with file input
catch( IOException ioException ) {
ioException.printStackTrace();
}
}
} // end anonymous inner class
); // end call to addActionListener
container.add( southPanel, BorderLayout.SOUTH );
setSize( 550, 225 );
setVisible( true );
} // end constructor
// output property values
public void listProperties()
{
StringBuffer buffer = new StringBuffer();
String name, value;
Enumeration enumeration = table.propertyNames();
while ( enumeration.hasMoreElements() ) {
name = enumeration.nextElement().toString();
value = table.getProperty( name );
buffer.append( name ).append( '\t' );
buffer.append( value ).append( '\n' );
}
displayArea.setText( buffer.toString() );
}
// display String in statusLabel label
public void showstatus( String s )
{
statusLabel.setText( s );
}
public static void main( String args[] )
{
PropertiesTest application = new PropertiesTest();
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
} // end class PropertiesTest
Bit manipulation and the Bitwise
// Fig. 21.8: MiscBitOps.java
// Using the bitwise operators.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MiscBitOps extends JFrame {
private JTextField input1Field, input2Field,
bits1Field, bits2Field, bits3Field, resultField;
private int value1, value2;
// set up GUI
public MiscBitOps()
{
super( "Bitwise operators" );
JPanel inputPanel = new JPanel();
inputPanel.setLayout( new GridLayout( 4, 2 ) );
inputPanel.add( new JLabel( "Enter 2 ints" ) );
inputPanel.add( new JLabel( "" ) );
inputPanel.add( new JLabel( "Value 1" ) );
input1Field = new JTextField( 8 );
inputPanel.add( input1Field );
inputPanel.add( new JLabel( "Value 2" ) );
input2Field = new JTextField( 8 );
inputPanel.add( input2Field );
inputPanel.add( new JLabel( "Result" ) );
resultField = new JTextField( 8 );
resultField.setEditable( false );
inputPanel.add( resultField );
JPanel bitsPanel = new JPanel();
bitsPanel.setLayout( new GridLayout( 4, 1 ) );
bitsPanel.add( new JLabel( "Bit representations" ) );
bits1Field = new JTextField( 33 );
bits1Field.setEditable( false );
bitsPanel.add( bits1Field );
bits2Field = new JTextField( 33 );
bits2Field.setEditable( false );
bitsPanel.add( bits2Field );
bits3Field = new JTextField( 33 );
bits3Field.setEditable( false );
bitsPanel.add( bits3Field );
JPanel buttonPanel = new JPanel();
// button to perform bitwise AND
JButton andButton = new JButton( "AND" );
buttonPanel.add( andButton );
andButton.addActionListener(
new ActionListener() { // anonymous inner class
// perform bitwise AND and display results
public void actionPerformed( ActionEvent event )
{
setFields();
resultField.setText( Integer.toString( value1 & value2 ) );
bits3Field.setText( getBits( value1 & value2 ) );
}
} // end anonymous inner class
); // end call to addActionListener
// button to perform bitwise inclusive OR
JButton inclusiveOrButton = new JButton( "Inclusive OR" );
buttonPanel.add( inclusiveOrButton );
inclusiveOrButton.addActionListener(
new ActionListener() { // anonymous inner class
// perform bitwise inclusive OR and display results
public void actionPerformed( ActionEvent event )
{
setFields();
resultField.setText( Integer.toString( value1 | value2 ) );
bits3Field.setText( getBits( value1 | value2 ) );
}
} // end anonymous inner class
); // end call to addActionListener
// button to perform bitwise exclusive OR
JButton exclusiveOrButton = new JButton( "Exclusive OR" );
buttonPanel.add( exclusiveOrButton );
exclusiveOrButton.addActionListener(
new ActionListener() { // anonymous inner class
// perform bitwise exclusive OR and display results
public void actionPerformed( ActionEvent event )
{
setFields();
resultField.setText( Integer.toString( value1 ^ value2 ) );
bits3Field.setText( getBits( value1 ^ value2 ) );
}
} // end anonymous inner class
); // end call to addActionListener
// button to perform bitwise complement
JButton complementButton = new JButton( "Complement" );
buttonPanel.add( complementButton );
complementButton.addActionListener(
new ActionListener() { // anonymous inner class
// perform bitwise complement and display results
public void actionPerformed( ActionEvent event )
{
input2Field.setText( "" );
bits2Field.setText( "" );
int value = Integer.parseInt( input1Field.getText() );
resultField.setText( Integer.toString( ~value ) );
bits1Field.setText( getBits( value ) );
bits3Field.setText( getBits( ~value ) );
}
} // end anonymous inner class
); // end call to addActionListener
Container container = getContentPane();
container.add( inputPanel, BorderLayout.WEST );
container.add( bitsPanel, BorderLayout.EAST );
container.add( buttonPanel, BorderLayout.SOUTH );
setSize( 600, 150 );
setVisible( true );
} // end constructor
// display numbers and their bit form
private void setFields()
{
value1 = Integer.parseInt( input1Field.getText() );
value2 = Integer.parseInt( input2Field.getText() );
bits1Field.setText( getBits( value1 ) );
bits2Field.setText( getBits( value2 ) );
}
// display bit representation of specified int value
private String getBits( int value )
{
// create int value with 1 in leftmost bit and 0s elsewhere
int displayMask = 1 << 31;
StringBuffer buffer = new StringBuffer( 35 ); // buffer for output
// for each bit append 0 or 1 to buffer
for ( int bit = 1; bit <= 32; bit++ ) {
// use displayMask to isolate bit
buffer.append( ( value & displayMask ) == 0 ? '0' : '1' );
value <<= 1; // shift value one position to left
if ( bit % 8 == 0 )
buffer.append( ' ' ); // append space to buffer every 8 bits
}
return buffer.toString();
} // end method getBits
public static void main( String args[] )
{
MiscBitOps application = new MiscBitOps();
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
} // end class MiscBitOps
// Fig. 21.11: BitShift.java
// Using the bitwise shift operators.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class BitShift extends JFrame {
private JTextField bitsField, valueField;
// set up GUI
public BitShift()
{
super( "Shifting bits" );
Container container = getContentPane();
container.setLayout( new FlowLayout() );
container.add( new JLabel( "Integer to shift " ) );
// textfield for user to input integer
valueField = new JTextField( 12 );
container.add( valueField );
valueField.addActionListener(
new ActionListener() { // anonymous inner class
// read value and display its bitwise representation
public void actionPerformed( ActionEvent event )
{
int value = Integer.parseInt( valueField.getText() );
bitsField.setText( getBits( value ) );
}
} // end anonymous inner class
); // end call to addActionListener
// textfield to display bitwise representation of an integer
bitsField = new JTextField( 33 );
bitsField.setEditable( false );
container.add( bitsField );
// button to shift bits left by one position