21.1 引出问题
一个问题?
前面我们学习了数组,充分体会到数组的优越性,就是可以存储同一类型的数据,但是我们假设有这样的需求,大家看看如何解决?
请做一个公司职员薪水管理系统,要求完成如下功能:
1、当有新员工时,将该员工加入到管理系统;
2、可以根据员工号,显示该员工的信息;
3、可以显示所有员工信息;
4、可以修改员工的薪水;
5、当员工离职时,将该员工从管理系统中删除;
6、可以按照薪水从低到高顺序排序;
7、可以统计员工的平均工资、最低和最高工资。
解决之道-链表或集合类:
我们想,如果有这样一种数组,可以动态的改变就好了,java的设计者为我们提供了一系列的集合类。
21.2 集合类分类
图中打红色三角的为常用的需要掌握的几个集合类。
从上面的图可以看出java集合类主要有以下几种:
1、List结构的集合类
ArrayList类,LinkedList(链表)类,Vector类,Stack类
2、Map结构的集合类
HashMap类,Hashtable类
3、Set结构的集合类
HashSet类,TreeSet类
4、Queue结构的集合
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 ArrayList和Vector的区别
ArrayList和Vector都是java的集合类,都可以用来存放java对象,这是它们的相同点,但是它们也是有区别的:
1、同步性:
Vector是同步的,这个类中的一些方法保证了Vector中的对象是线程安全的。
ArrayList是异步的,因此ArrayList中的对象并不是线程安全的。
因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合,那么使用ArrayList是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销。
Tricks:单机的程序一般不涉及同步性;做服务器的时候会涉及同步性。
2、数据增长:
从内部实现机制来讲,ArrayList和Vector都是使用数组(Array)来控制集合中的对象。当你想这两种类型中增加元素的时候,如果元素的数目超出了内部数组目前的长度,它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据,那么使用Vector有一些优势,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。
21.5 HashMap和Hashtable的区别
HashMap与Hashtable都是java的集合类,都可以用来存放java对象,这是他们的相同点,但是它们也有区别:
1、历史原因:
Hashtable是基于陈旧的Dictionary类的。
HashMap是java 1.2引进的Map接口的一个实现。
2、同步性:
Hashtable是同步的,这个类的一些方法保证了Hashtable中的对象是线程安全的。
HashMap是异步的,因此HashMap中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合,那么使用HashMap是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销,从而提高效率。
3、值:HashMap可以让你将空值(null)作为一个表的条目的key或value,但是Hashtable是不能放入空值(null)的。
21.6 经验总结
进一步理解集合框架
Java的设计者给我们提供了这些集合类,在后面编程中是相当有用的,具体什么时候用什么集合,要根据我们刚才分析的集合异同来选取。
韩顺平经验总结:
1、如果要求线程安全,使用Vector、Hashtable;
2、如果不要求线程安全,应使用ArrayList、LinkedList、HashMap;
3、如果要求键值时,则使用HashMap、Hashtable;
4、如果数据量很大,又要线程安全考虑Vector。