21.1 引出问题

一个问题?

前面我们学习了数组,充分体会到数组的优越性,就是可以存储同一类型的数据,但是我们假设有这样的需求,大家看看如何解决?

请做一个公司职员薪水管理系统,要求完成如下功能:

1、当有新员工时,将该员工加入到管理系统;

2、可以根据员工号,显示该员工的信息;

3、可以显示所有员工信息;

4、可以修改员工的薪水;

5、当员工离职时,将该员工从管理系统中删除;

6、可以按照薪水从低到高顺序排序;

7、可以统计员工的平均工资、最低和最高工资。

解决之道-链表或集合类:

我们想,如果有这样一种数组,可以动态的改变就好了,java的设计者为我们提供了一系列的集合类。

21.2 集合类分类

图中打红色三角的为常用的需要掌握的几个集合类。

 

从上面的图可以看出java集合类主要有以下几种:

1List结构的集合类

ArrayList类,LinkedList(链表)类,Vector类,Stack

2Map结构的集合类

HashMap类,Hashtable

3Set结构的集合类

HashSet类,TreeSet

4Queue结构的集合

Queue接口

21.3 List结构的集合类

ArrayList类,LinkedList(链表)类,Vector类,Stack

 

21.3.1 ArrayList

 

上图为结合代码画出的内存中的运行示意图。

演示代码如下:

 1 /**日期:2016-03-07
 2  * 功能:ArrayList演示
 3  */
 4 package test;
 5 //所有集合类都在java.util包中
 6 import java.util.*;
 7 public class Demo2 {
 8 
 9     public static void main(String[] args) {
10         // TODO Auto-generated method stub
11         
12         ArrayList al=new ArrayList();
13         System.out.println("此时al的长度为"+al.size());
14         
15         Clerk clerk1=new Clerk("宋江",50,1000);
16         Clerk clerk2=new Clerk("吴用",45,1200);
17         Clerk clerk3=new Clerk("林冲",35,1500);
18         
19         //添加职员对象
20         //有两种add方法,下面这种方式是将新对象添加到ArrayList的最后
21         //还有一种add方法是,将新对象添加到指定的位置
22         al.add(clerk1);
23         al.add(clerk2);
24         al.add(clerk3);
25         al.add(clerk1); //注意:可以重复添加一个对象
26         System.out.println("此时al的长度为"+al.size());
27         
28         //遍历al,打印出每个职员的名字
29         for(int i=0;i<al.size();i++)
30         {
31             //需要实例化一个临时变量,来完成名字的读取
32             Clerk temp=(Clerk)al.get(i); 
33             System.out.println("第"+i+"个人的名字为:"+temp.getName());
34         }
35         
36         System.out.println("====删除吴用之后====");
37         //删除职员对象
38         al.remove(1);
39         for(int i=0;i<al.size();i++)
40         {
41             Clerk temp=(Clerk)al.get(i);
42             System.out.println("第"+i+"个人的名字为:"+temp.getName());
43         }
44     }
45 
46 }
47 
48 class Clerk
49 {
50     private String name;
51     private int age;
52     private int salary;
53     
54     public String getName() {
55         return name;
56     }
57     public void setName(String name) {
58         this.name = name;
59     }
60     public int getAge() {
61         return age;
62     }
63     public void setAge(int age) {
64         this.age = age;
65     }
66     public int getSalary() {
67         return salary;
68     }
69     public void setSalary(int salary) {
70         this.salary = salary;
71     }
72 
73     public Clerk(String name,int age,int salary)
74     {
75         this.name=name;
76         this.age=age;
77         this.salary=salary;
78     }
79     
80 }
View Code

运行结果如下:

 1 此时al的长度为0
 2 此时al的长度为4
 3 第0个人的名字为:宋江
 4 第1个人的名字为:吴用
 5 第2个人的名字为:林冲
 6 第3个人的名字为:宋江
 7 ====删除吴用之后====
 8 第0个人的名字为:宋江
 9 第1个人的名字为:林冲
10 第2个人的名字为:宋江
View Code

 

21.2.2 LinkedList

链表

用法同ArrayList基本相同。

ArrayList增加了一些方法,比如addFirst(往前面加)、addLast(往后面加)等。

21.2.3 Vector

向量

用法同ArrayList基本相同。

21.2.4 Stack

用法同ArrayList基本相同。

add时是往前面加。

21.4 Map结构的集合类

21.4.1 HashMap

 演示代码如下:

 1 /**日期:2016-03-06
 2  * 功能:HashMap,Hashtable演示
 3  */
 4 package test;
 5 import java.util.*;
 6 public class Demo3 {
 7 
 8     public static void main(String[] args) {
 9         // TODO Auto-generated method stub
10         
11         //创建一个HashMap对象
12         HashMap hm=new HashMap();
13         
14         Emp emp1=new Emp("s001","花荣",1200.5f);
15         Emp emp2=new Emp("s002","李逵",1010.5f);
16         Emp emp3=new Emp("s003","晁盖",1500.5f);
17         //将emp放到hm中,s001等为键(key),emp1等为值(value)
18         hm.put("s001", emp1);
19         hm.put("s002", emp2);
20         hm.put("s003", emp3);
21         hm.put("s001", emp3); //该条语句会用emp3覆盖emp1,结果s001对应emp1
22         hm.put("s001", emp1); //覆盖回来
23         
24         //查找编号对应的员工
25         if(hm.containsKey("s001"))
26         {
27             System.out.println("有该员工!");
28             //取出该员工的姓名,hm.get("s001")为Object对象,需要转换成Emp对象,参考float转换成int
29             System.out.println("该员工的姓名为:"+((Emp)(hm.get("s001"))).getName());
30         }else
31         {
32             System.out.println("没有该员工!");
33         }
34         System.out.println();
35         
36         //遍历HashMap中的所有key和value,稍微麻烦
37         //Iterator迭代
38         Iterator it=hm.keySet().iterator();
39         //hasNext返回一个boolean值
40         while(it.hasNext())
41         {
42             //取出key,it.next()为Object对象,通过头String()转换为String对象
43             String key=it.next().toString();
44             //通过key去除value
45             Emp emp=(Emp)hm.get(key);
46             System.out.println("员工编号:"+emp.getEmpNo());
47             System.out.println("员工姓名:"+emp.getName());
48             System.out.println("员工薪水:"+emp.getSal());
49         }
50         System.out.println();
51         //HashMap可以放入空值null
52         HashMap hm1=new HashMap();
53         hm1.put(null,null);
54         System.out.println("空值的结果为:"+hm1.get(null));
55     }
56 
57 }
58 
59 class Emp
60 {
61     private String EmpNo;
62     private String name;
63     private float sal;
64     
65     public Emp(String EmpNo,String name,float sal)
66     {
67         this.EmpNo=EmpNo;
68         this.name=name;
69         this.sal=sal;
70     }
71         
72     public String getEmpNo() {
73         return EmpNo;
74     }
75 
76     public void setEmpNo(String empNo) {
77         EmpNo = empNo;
78     }
79 
80     public String getName() {
81         return name;
82     }
83 
84     public void setName(String name) {
85         this.name = name;
86     }
87 
88     public float getSal() {
89         return sal;
90     }
91 
92     public void setSal(float sal) {
93         this.sal = sal;
94     }
95 }
View Code

运行结果如下:

 1 有该员工!
 2 该员工的姓名为:花荣
 3 
 4 员工编号:s001
 5 员工姓名:花荣
 6 员工薪水:1200.5
 7 员工编号:s002
 8 员工姓名:李逵
 9 员工薪水:1010.5
10 员工编号:s003
11 员工姓名:晁盖
12 员工薪水:1500.5
13 
14 空值的结果为:null
View Code

 

21.4.2 Hashtable

用法同HashMap基本相同。

21.5 ArrayListVector的区别

ArrayListVector都是java的集合类,都可以用来存放java对象,这是它们的相同点,但是它们也是有区别的:

1、同步性:

Vector是同步的,这个类中的一些方法保证了Vector中的对象是线程安全的。

ArrayList是异步的,因此ArrayList中的对象并不是线程安全的。

因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合,那么使用ArrayList是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销。

 

Tricks:单机的程序一般不涉及同步性;做服务器的时候会涉及同步性。

 

2、数据增长:

从内部实现机制来讲,ArrayListVector都是使用数组(Array)来控制集合中的对象。当你想这两种类型中增加元素的时候,如果元素的数目超出了内部数组目前的长度,它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据,那么使用Vector有一些优势,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。

21.5 HashMapHashtable的区别

HashMapHashtable都是java的集合类,都可以用来存放java对象,这是他们的相同点,但是它们也有区别:

1、历史原因:

Hashtable是基于陈旧的Dictionary类的。

HashMapjava 1.2引进的Map接口的一个实现。

2、同步性:

Hashtable是同步的,这个类的一些方法保证了Hashtable中的对象是线程安全的。

HashMap是异步的,因此HashMap中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合,那么使用HashMap是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销,从而提高效率。

3、值:HashMap可以让你将空值(null)作为一个表的条目的keyvalue,但是Hashtable是不能放入空值(null)的。

 

21.6 经验总结

进一步理解集合框架

Java的设计者给我们提供了这些集合类,在后面编程中是相当有用的,具体什么时候用什么集合,要根据我们刚才分析的集合异同来选取。

韩顺平经验总结:

1、如果要求线程安全,使用VectorHashtable

2、如果不要求线程安全,应使用ArrayListLinkedListHashMap

3、如果要求键值时,则使用HashMapHashtable

4、如果数据量很大,又要线程安全考虑Vector