韩顺平循序渐进学java 第21.22.23.24讲 集合
韩顺平循序渐进学java 第21.22.23.24讲 集合
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 }
运行结果如下:
1 此时al的长度为0 2 此时al的长度为4 3 第0个人的名字为:宋江 4 第1个人的名字为:吴用 5 第2个人的名字为:林冲 6 第3个人的名字为:宋江 7 ====删除吴用之后==== 8 第0个人的名字为:宋江 9 第1个人的名字为:林冲 10 第2个人的名字为:宋江
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 }
运行结果如下:
1 有该员工! 2 该员工的姓名为:花荣 3 4 员工编号:s001 5 员工姓名:花荣 6 员工薪水:1200.5 7 员工编号:s002 8 员工姓名:李逵 9 员工薪水:1010.5 10 员工编号:s003 11 员工姓名:晁盖 12 员工薪水:1500.5 13 14 空值的结果为:null
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。