• 1. Java集合框架
  • 2. 本章内容1. Java集合框架概述 2.List接口以及实现类 3.Set接口以及实现类 4.Map接口以及实现类 5.Boxing/unBoxing 6.Iterator以及Enumeration接口 7.Collections和Arrays类
  • 3. 集合框架的概念集合就是将若干用途相同、近似的“数据”结合成一个整体。 集合从体系上分为三种: (1) 列表(List):List集合区分元素的顺序,允许包含相同的元素。 (2) 集(Set):Set集合不区分元素的顺序,不允许包含相同的元素。 (3) 映射(Map):Map集合保存的”键”-“值”对,“键”不能重复,而且一个“键”只能对应一个“值”。 Java集合中只能保存引用数据类型,也就是保存的是对象的地址,而非对象本身。集合中元素相当于引用类型的变量。
  • 4. 集合框架的类图关系JDK所提供的容器API全部位于java.util包中。 容器API的类图关系如下:
  • 5. Collection接口中的方法(1) int size(); (2) boolean isEmpty(); (3) void clear(); (4) boolean contains(Object element); (5) boolean add(Object element); (6) boolean remove(Object element); (7) Iterator iterator(); (8) boolean containsAll(Collection c); (9) boolean addAll(Collection c) (10) boolean removeAll(Collection c) (11) boolean retainAll(Collection c) (12) Object[] toArray();
  • 6. Collection方法举例import java.util.*; public class CollectionTest { public static void main(String args[]) { Collection c=new ArrayList(); c.add("hello world"); c.add(new Integer(100)); c.add(new Float(99.9f)); System.out.println(c.size()); System.out.println(c); } }
  • 7. List接口List是Collection的子接口,实现List接口的容器中存放的对象是有顺序的,而且可以重复。 List容器中存放的对象都有一个整数型的序号,记录该对象在容器中的位置,可以根据序号来访问容器中的元素。 JDK提供实现List接口的类有ArrayList、LinkedList等。 Object get(int index) Object set(int index,Object obj) void add(int index,Object obj) Object remove(int index) int indexOf(Object obj) int lastIndexOf(Object obj)
  • 8. List接口举例 List li=new ArrayList(); for(int i=0;i<10;i++) li.add("a"+i); System.out.println(li); li.add(3,"a20"); System.out.println(li); li.set(4,"a30"); System.out.println(li); System.out.println((String)li.get(2)); li.remove(0); System.out.println(li); 见源文件:List/ListTest1.java
  • 9. List接口的实现类-ArrayListjava.util.ArrayList实现了List接口,用于描述长度可变的数组列表(底层采用数组实现)。 ArrayList允许元素取值为null,提供了一些新增的方法来操作列表的容量的大小。 public ArrayList()(默认大小是10) public ArrayList(int initialCapacity) public void ensureCapacity(int minCapacity) public void trimToSize()
  • 10. List接口的实现类-ArrayList 1. 集合中存放的依然是对象的引用而不是对象本身。 2. ArrayList底层采用数组实现,当使用不带参数的构造方法生成ArrayList对象时,实际上会在底层生成一个长度为10的Object类型数组 3. 如果增加的元素个数超过了10个,那么ArrayList底层会新生成一个数组,长度为原数组的1.5倍+1,然后将原数组的内容复制到新数组当中,并且后续增加的内容都会放到新数组当中。当新数组无法容纳增加的元素时,重复该过程。 (跟进看源码就知道了) 4. 对于ArrayList元素的删除操作,需要将被删除元素的后续元素向前移动,代价比较高。 5. 集合当中只能放置对象的引用,无法放置原生数据类型,我们需要使用原生数据类型的包装类才能加入到集合当中。 6. 集合当中放置的都是Object类型,因此取出来的也是Object类型,那么必须要使用强制类型转换将其转换为真正的类型(放置进去的类型或用泛型) 7. 关于ArrayList与LinkedList的比较分析 a) ArrayList底层采用数组实现,LinkedList底层采用双向链表实现。 b) 当执行插入或者删除操作时,采用LinkedList比较好。 c) 当执行搜索操作时,采用ArrayList比较好。
  • 11. ArrayList举例 ArrayList list=new ArrayList(6); list.add("oyhj"); list.add(new Integer(10)); list.add(new Double(10.5)); System.out.println(list.size()); Object item[]=list.toArray(); for(int i=0;i
  • 12. List接口的实现类-Vectorjava.util.Vector实现了List接口,用于描述长度可变的数组向量(底层采用数组实现)。 与ArrayList的区别:Vector是线程安全的(同步),用在多线程环境中,运行效率慢。ArrayList不是线程安全的,用在单线程环境中。 Vector类的新增方法: public Vector()(默认大小是10) public Object elementAt(int index) public void removeElement(int index) public void insertElement(Object obj,int index) public boolean removeElement(Object obj) public void removeAllElements() public Object toArray()
  • 13. Vector-练习向Vector类的对象中添加5位学生对象,在下标为2的元素处,插入一个学生对象,将Vector对象转换成数组,打印出学生对象的信息。 学生Student类,属性包括学号、姓名和年龄。 见源文件:Vector/VectorTest.java
  • 14. Stack类java.util.Statck继承自Vector类,对应”First In,Last out”的数据结构-栈。 Stack类的常用方法: public Statck() public Object push(Object obj) public Object pop() public Object peek() public boolean isEmpty() public void clear() public int search(Object obj) 见源文件:Stack/StackTest.java
  • 15. Set接口Set接口是Collection的子接口,Set接口没有提供新增的方法,但实现Set接口的容器中元素是没有顺序的且不可以重复。 Set容器可以与数学中的“集合”概念相对应。 JDK中提供的实现Set接口的类有HashSet、TreeSet等。
  • 16. HashSetHashSet hs=new HashSet(); hs.add("first"); hs.add("second"); hs.add("third"); hs.add("fourth"); hs.add("first"); hs.add(new Date()); System.out.println("哈希表的大小:"+hs.size()); System.out.println(hs); 见源文件: HashSet/HashSetTest.java
  • 17. 关于Set中的重复元素思考:Set中不能存放重复的元素,那么请问什么样的元素属于重复元素。 见源文件:HashSet/SetTest.java Set集合中不能存放这样的元素: e1.equals(e2)为true。 注意:HashSet集合在设计时,为了避免多次调用equals方法带来的效率降低问题,当新添加对象时,首先调用该对象的hashcode()方法,如果hashcode()得到的地址没有被对象占据,就将该新对象插入;如果hashcode()值已经被占用了,再调用equals()方法与占用该位置的对象比较,如果为true,这两个对象才是认为是重复元素,新对象就不会被添加进来;如果为false,再利用散列算法放到其它地址上。 加入到HashSet集合中的对象,一定要重写equas()和hashCode()两个方法。
  • 18. hashCode()方法的进一步探讨 一旦一个对象加入到HashSet集合中后,就不要再改变那些参与计算该对象hashcode值的属性的值了。否则就会改变该对象在HashSet中的位置,而造成内存泄露。 见源文件:HashSet/SetTest3.java
  • 19. Set接口与集合操作相关的几个方法 Set s1=new HashSet(); Set s2=new HashSet(); s1.add("a");s1.add("b");s1.add("c"); s2.add("b");s2.add("c");s2.add("d"); Set s3=new HashSet(s1); s3.retainAll(s2);//求交集 Set s4=new HashSet(s2); s4.addAll(s1);//求并集 Set s5=new HashSet(s1); s5.removeAll(s3);//求差 System.out.println(s3); System.out.println(s4); System.out.println(s5); 见源文件: HashSet/SetTest2.java
  • 20. Set接口的实现类-TreeSetTreeSet描述的是Set的一个变体-可实现排序功能的集合。 将对象插入到TreeSet中时,会按照某种比较规则将对象插入到一个有序序列中,以保证TreeSet集合中的对象序列保持“升序”排列。 见源文件:TreeSet/TreeSetTest1.java
  • 21. Comparable接口 问题:TreeSet中的排序方法是根据什么确定对象之间的”大小”关系呢? 所有可排序的类都实现了java.lang.Comparable接口,该接口中只有一个抽象方法: public int compareTo(Object obj) 注意:用户在实现compareTo()方法确定比较逻辑时,比较结果应该和equals()方法比较的结果一致。 见源文件:Comparable/TreeSetTest2.java
  • 22. Map接口实现Map接口的类用来存储”键-值”对。 可理解为一张二维表,这个二维表只有两列,一列是Key,一列是Value。 Map中存储的“键-值”对由键来标识,所以键不能重复。 Map接口的实现类有HashMap和TreeMap。 Map接口的常用方法: Object put(Object key,Object value) Object get(Object key) Object remove(Object key) boolean containsKey(Object key) boolean containsValue(Object value) int size() boolean isEmpty() void putAll(Map t) void clear()
  • 23. Map接口的实现类-HashMapjava.util.HashMap类实现了java.util.Map接口,基于哈希表实现“键”-“值”对的映射关系。 HashMap不确定“K”-”value”对的先后顺序,允许使用null “K”和null”value”。 影响HashMap性能的两个因素: 初始容量(Initial Capacity) 加载因子(Load Factor) (小于1的数) 见源文件: HashMap/HashMapTest1.java
  • 24. Map接口的实现类-Hashtable java.util.Hashtable实现了java.util.Map接口,也是采用哈希表的形式将”Key”映射到”Value”,用法与HashMap基本相同。 HashMap与Hashtable的区别: (1) Hashtable中的“key”和“value”都不允许null,而HashMap允许。 (2) Hashtable是线程安全的,适合在多用户环境中使用,效率稍低;HashMap不是线程安全的,效率稍高,适合在单线程环境下使用。
  • 25. Map接口-练习1. 结合Map接口来统计字符串数组中不同字符串的个数。(字符串数组由main()方法的参数获取) for(int i=0;i
  • 26. Iterator接口Iterator(称作迭代器)接口主要提供了对容器中元素进行遍历的方法。 所有实现了Collection接口的类都有一个iterator()方法来返回一个实现了Iterator接口的类的对象。 该接口中定义了如下抽象方法:
  • 27. Iterator接口boolean hasNext() //判断游标右边是否还有元素 Object next() //返回游标右边的元素并将游标移动到该元素后 void remove() //删除游标左边的元素,通常在next()方法之后执行,只执行一次。
  • 28. Iterator接口举例 Collection c=new ArrayList(); c.add("hello world"); c.add(new Integer(100)); c.add(new Float(99.9f)); Iterator it=c.iterator(); while(it.hasNext()) { Object obj=it.next(); System.out.println(obj); it.remove(); } System.out.println(c); 见源文件:Iterator/IteratorTest.java
  • 29. Enumeration接口Enumeration接口的功能与Iterator接口类似,也能够对集合中的元素进行遍历。但是Enumeration接口只对Vector、Hashtable类提供遍历方法,并且不支持移除操作。 boolean hasMoreElements() //判断此枚举中是否有下一个元素 Object nextElement() //返回枚举中的下一个元素 见源文件:Enumeraiton/EnumerationTest.java
  • 30. List常用算法-由Collections类实现java.util.Collections类提供了一些静态方法,实现了基于List容器的常用算法。 void sort(List list) 对容器内的元素进行升序排序 void reverse(List list) 对容器内的元素进行逆序排列 void shuffle(List list) 对List容器内的元素进行随机排列 void fill(List list,Object obj) 对特定的对象来填充list void copy(List des,List src) 将src容器中的内容拷贝到des容器中 Object max(Colletion c) Object min(Collection c) void rotate(List list,int distance) 对列表中元素按distance进行移位操作 int binarySearch(List list,Object obj) 采用折半查找在list中寻找obj对象,返回这个对象在容器中的位置 (注意调用此方法前必须对列表进行升序排序,否则结果不确定) 见源文件:Collections/CollectiosTest.java
  • 31. Arrays类java.util.Arrays类提供了对数组进行操作的静态方法,实现了对数组元素进行排序、查找、转换为字符串形式和列表等功能。 List asList(Object a[ ]) Void sort(Object a[ ]) String toString(Object a[ ]) int binarySearch(Object a[ ],Object key) 见源文件:Arrays/ArraysTest.java
  • 32. JDK1.5增强的for循环增强的for循环对于遍历Array和Collection的时候相当便利。 int array[]={1,2,3,4,5}; for(int i:array) System.out.println(i); Collection c=new ArrayList(); c.add("hello world"); c.add(new String("oyhj")); c.add(new Float(99.9f)); for(Object obj:c) System.out.println(obj);
  • 33. 增强的For循环缺点: 数组:不能通过下标访问数组元素 集合:与使用Iterator相比,不能方便的删除集合中的元素。 注:除了简单的遍历读取内容外,不建议使用增强的for循环。
  • 34. Auto Boxing/unBoxingJDK1.5支持在适当时候自动打包/解包的功能 打包:自动将基础数据类型转换成与之对应的封 装类的对象 解包:自动将封装类的对象转换成与之对应的基本数据类型
  • 35. Map m1=new HashMap(); Map m2=new TreeMap(); m1.put("first",1); m1.put("second",2); m1.put("third",3); m2.put("one",1); m2.put("two",3); System.out.println(m1.size()); System.out.println(m1.containsKey("first")); System.out.println(m2.containsValue(2)); if(m1.containsKey("second")) System.out.println(m1.get("second")); 见源文件:BoxingTest.java
  • 36. 综合练习 定义一个类,该类能够完成商品的添加、删除(根据商品的ID号)、遍历和计算商品总价操作。 商品类包括的属性有:ID、单价、数量 见原文件:综合练习/Test.java
  • 37. 本章总结 1-2-2-6阵形 1个图 (门将) 2个类(Collections,Arrays) (前锋) 2个知识点 (中场) 增强的For循环 Auto-boxing/unboxing 6个接口 (后卫) Collection Set List Map Iterator Comparable