JDK CHM文档

1.1、主要集合概述

Java集合主要有3种重要的类型:

  1. List:是一个有序集合,可以放重复的数据(底层是数组)
  2. Set:是一个无序集合,不允许放重复的数据(底层是map的key)
  3. Map:是一个无序集合,集合中包含一个键对象,一个值对象,键对象不允许重复,值对象可以重复(身份证号—姓名)

![PQ}VFY78S]RW0[1Q%(HTL.png](https://cdn.nlark.com/yuque/0/2022/png/23145762/1648288002597-b98e43e7-2e8b-4df4-a1e1-69d894090ecd.png#clientId=u46bddb6f-70cf-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=357&id=ue5a2f7f5&margin=%5Bobject%20Object%5D&name=PQ%7DVFY78S%5DRW0%5B1Q%25%28HTL.png&originHeight=446&originWidth=821&originalType=binary&ratio=1&rotation=0&showTitle=false&size=27771&status=done&style=shadow&taskId=u9f5a00e6-4208-4479-b2a7-c3c831ac880&title=&width=656.8)

1.2、Collection和Iterator

Collection是List和Set的父接口,在Collection中定义了一些主要方法

boolean add(E o)
确保此 collection 包含指定的元素(可选操作)。
boolean addAll(Collection<? extends E> c)
将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
void clear()
移除此 collection 中的所有元素(可选操作)。
boolean contains(Object o)
如果此 collection 包含指定的元素,则返回 true。
boolean containsAll(Collection<?> c)
如果此 collection 包含指定 collection 中的所有元素,则返回 true。
boolean equals(Object o)
比较此 collection 与指定对象是否相等。
int hashCode()
返回此 collection 的哈希码值。
boolean isEmpty()
如果此 collection 不包含元素,则返回 true。
Iterator iterator()
返回在此 collection 的元素上进行迭代的迭代器。
boolean remove(Object o)
从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
boolean removeAll(Collection<?> c)
移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
boolean retainAll(Collection<?> c)
仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
int size()
返回此 collection 中的元素数。
Object[] toArray()
返回包含此 collection 中所有元素的数组。

T[] toArray(T[] a)
返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。

关于Iterator接口说明,Iterator称为迭代接口,通过此接口可以遍历集合中的数据,此接口主要方法为:

boolean hasNext()
如果仍有元素可以迭代,则返回 true。
E next()
返回迭代的下一个元素。

1.3、List接口

1.3.1、List接口概述

List接口下面主要有两个实现ArrayList和LinkedList,他们都是有顺序的,也就是放进去是什么顺序,取出来还是什么顺序,也就是基于线性存储,可以看作是一个可变数组.

  1. ArrayList:查询数据比较快,添加和删除数据比较慢(基于可变数组)

数组查找是基于下标的物理查找,所以比较快

  1. LinkedList:查询数据比较慢,添加和删除数据比较快(基于链表数据结构)
  2. Vector:和ArrayList类似的,都是数组,只不过是线程安全的,加了synchronized ```java import java.util.*;

public class ArrayListTest01 {

  1. public static void main(String[] args) {
  2. //最好不要这样写,这样属于面向具体编程了
  3. //无法达到灵活互换
  4. //最好面向接口编程
  5. ArrayList arrayList = new ArrayList();
  6. //采用面向接口编程
  7. //使用Collection会更灵活,如果List不能满足要求
  8. //那么可以采用HashSet,因为HashSet也实现了该接口
  9. Collection c = new ArrayList();
  10. //面向接口编程
  11. //采用list接口可以使用Collection里的方法
  12. //也可以使用list接口扩展的方法
  13. List l = new ArrayList();
  14. //自动装箱,适合于jdk1.5
  15. l.add(1);
  16. l.add(3);
  17. //jdk1.5以前,必须如下使用
  18. l.add(new Integer(2));
  19. l.add(new Integer(4));
  20. //可以加入重复数据
  21. l.add(2);
  22. //不能加入字符串
  23. //在强制转换时会出现ClassCastException错误
  24. //l.add("sadfdsfs");
  25. //可以采用List接口的中get()方法依次取得元素
  26. //输出结果为,不会打乱顺序
  27. /*
  28. 1
  29. 3
  30. 2
  31. 4
  32. 2
  33. */
  34. for (int i=0; i<l.size(); i++) {
  35. //将Object强制转换为Integer
  36. Integer e = (Integer)l.get(i);
  37. System.out.println(e);
  38. }
  39. System.out.println("");
  40. //调用remove删除集合中的元素
  41. //如果元素重复会remove掉第一个匹配的
  42. l.remove(2);
  43. //采用Iterator遍历数据(while循环)
  44. //Iterator是一种模式,主要可以统一数据结构的访问方式
  45. //这样在程序中就不用关心各个数据结构的实现了
  46. //使对不同数据结构的遍历更加简单了,更加统一了
  47. Iterator iter = l.iterator();
  48. while (iter.hasNext()) {
  49. Integer v = (Integer)iter.next();
  50. System.out.println(v);
  51. }
  52. System.out.println("");
  53. //采用Iterator遍历数据(for循环)
  54. for (Iterator iter1=l.iterator(); iter1.hasNext();) {
  55. Integer v = (Integer)iter1.next();
  56. System.out.println(v);
  57. }
  58. //在集合中是否包含3,输出为:true
  59. System.out.println(l.contains(3));
  60. //集合是否为空,输出:false
  61. System.out.println(l.isEmpty());
  62. System.out.println("");
  63. //转换成对象数组
  64. Object[] oArray1 = l.toArray();
  65. for (int i=0; i<oArray1.length; i++) {
  66. Integer v = (Integer)oArray1[i];
  67. System.out.println(v);
  68. }
  69. System.out.println("");
  70. //运行时自动创建相应类型的数组
  71. Integer[] iArray = new Integer[l.size()];
  72. l.toArray(iArray);
  73. for (int i=0; i<iArray.length; i++) {
  74. int v = iArray[i];
  75. System.out.println(v);
  76. }
  77. }

}

  1. <a name="Jz5Uw"></a>
  2. ### **1.3.2、LinkedList**
  3. 用法同ArrayList
  4. ```java
  5. import java.util.*;
  6. public class LinkedListTest01 {
  7. public static void main(String[] args) {
  8. //最好不要这样写,这样属于面向具体编程了
  9. //无法达到灵活互换
  10. //最好面向接口编程
  11. LinkedList arrayList = new LinkedList();
  12. //采用面向接口编程
  13. //使用Collection会更灵活,如果List不能满足要求
  14. //那么可以采用HashSet,因为HashSet也实现了该接口
  15. Collection c = new LinkedList();
  16. //面向接口编程
  17. //采用list接口可以使用Collection里的方法
  18. //也可以使用list接口扩展的方法
  19. //List l = new ArrayList();
  20. //因为LinkedList和ArrayList都实现了List接口,所以我们可以灵活互换
  21. //直接修改为LinkedList,对我们的程序没有任何影响
  22. List l = new LinkedList();
  23. //自动装箱,适合于jdk1.5
  24. l.add(1);
  25. l.add(3);
  26. //jdk1.5以前,必须如下使用
  27. l.add(new Integer(2));
  28. l.add(new Integer(4));
  29. //可以加入重复数据
  30. l.add(2);
  31. for (int i=0; i<l.size(); i++) {
  32. Integer e = (Integer)l.get(i);
  33. System.out.println(e);
  34. }
  35. System.out.println("");
  36. l.remove(2);
  37. Iterator iter = l.iterator();
  38. while (iter.hasNext()) {
  39. Integer v = (Integer)iter.next();
  40. System.out.println(v);
  41. }
  42. System.out.println("");
  43. for (Iterator iter1=l.iterator(); iter1.hasNext();) {
  44. Integer v = (Integer)iter1.next();
  45. System.out.println(v);
  46. }
  47. System.out.println(l.contains(3));
  48. System.out.println(l.isEmpty());
  49. System.out.println("");
  50. Object[] oArray1 = l.toArray();
  51. for (int i=0; i<oArray1.length; i++) {
  52. Integer v = (Integer)oArray1[i];
  53. System.out.println(v);
  54. }
  55. System.out.println("");
  56. Integer[] iArray = new Integer[l.size()];
  57. l.toArray(iArray);
  58. for (int i=0; i<iArray.length; i++) {
  59. int v = iArray[i];
  60. System.out.println(v);
  61. }
  62. }
  63. }

修改为HashSet实现类,重点了解面向接口编程的好处

  1. import java.util.*;
  2. public class LinkedListTest02 {
  3. public static void main(String[] args) {
  4. //采用面向接口编程
  5. //使用Collection会更灵活,如果List不能满足要求
  6. //那么可以采用HashSet,因为HashSet也实现了该接口
  7. //Collection c = new LinkedList();
  8. //可以修改为HashSet
  9. Collection c = new HashSet();
  10. //不能改为HashSet,因为HashSet不是List产品
  11. //List l = new HashSet();
  12. //自动装箱,适合于jdk1.5
  13. c.add(1);
  14. c.add(3);
  15. //jdk1.5以前,必须如下使用
  16. c.add(new Integer(2));
  17. c.add(new Integer(4));
  18. //可以加入重复数据
  19. c.add(2);
  20. /*
  21. for (int i=0; i<c.size(); i++) {
  22. //不能采用get,因为get是List接口扩展的
  23. //父类不能看到子类扩展的功能
  24. //反过来子类可以看到父类的功能,因为子类继承了父类
  25. Integer e = (Integer)c.get(i);
  26. System.out.println(e);
  27. }
  28. */
  29. System.out.println("");
  30. Iterator iter = c.iterator();
  31. while (iter.hasNext()) {
  32. Integer v = (Integer)iter.next();
  33. System.out.println(v);
  34. }
  35. System.out.println("");
  36. for (Iterator iter1=c.iterator(); iter1.hasNext();) {
  37. Integer v = (Integer)iter1.next();
  38. System.out.println(v);
  39. }
  40. System.out.println(c.contains(3));
  41. System.out.println(c.isEmpty());
  42. System.out.println("");
  43. Object[] oArray1 = c.toArray();
  44. for (int i=0; i<oArray1.length; i++) {
  45. Integer v = (Integer)oArray1[i];
  46. System.out.println(v);
  47. }
  48. System.out.println("");
  49. Integer[] iArray = new Integer[c.size()];
  50. c.toArray(iArray);
  51. for (int i=0; i<iArray.length; i++) {
  52. int v = iArray[i];
  53. System.out.println(v);
  54. }
  55. }
  56. }

1.3.3、Vector

  1. //Vector的用法
  2. Vector vv=new Vector();
  3. AEmp emp1=new AEmp("1","aa",1.2f);
  4. AEmp emp2=new AEmp("2","bb",1.2f);
  5. AEmp emp3=new AEmp("3","cc",1.2f);
  6. vv.add(emp1);
  7. vv.add(emp2);
  8. vv.add(emp3);
  9. //遍历
  10. for(int i=0;i<vv.size();i++){
  11. AEmp emp=(AEmp)vv.get(i);
  12. System.out.println(emp.getName());
  13. }

ArrayList和Vector的区别
相同点:都是java的集合类,都可以用来存放java对象
不同点:
1、同步性 (Vector是线程同步的,ArrayList则是线程异步的)
2、数据增长

1.4、Set接口

1.4.1、哈希表

哈希表是一种数据结构,哈希表能够提供快速存取操作。哈希表是基于数组的,所以也存在缺点,数组一旦创建将不能扩展。
正常的数组,如果需要查询某个值,需要对数组进行遍历,只是一种线性查找,查找的速度比较慢。如果数组中的元素值和下标能够存在明确的对应关系,那么通过数组元素的值就可以换算出数据元素的下标,通过下标就可以快数定位数组元素,这样的数组就是哈希表。

一张哈希表:

元素值 10 11 12 13 14 15 16 17 18
元素下标 0 1 2 3 4 5 6 7 8

以上我们的示例元素值和下标的关系为:
元素下标=元素值-10,此时的示例hashcode就是和数组下标一致了,取得hashcode方法如下:

  1. //取得hashCode
  2. pubic int hashCode(int value) {
  3. return value 10;
  4. }

有了hashCode后,我们就可以快速的定位相应的元素,查找到相应的信息

1.4.2、HashSet

HashSet中的数据是无序的不可重复的。HashSet按照哈希算法存取数据的,具有非常好性能,它的工作原理是这样的,当向HashSet中插入数据的时候,他会调用对象的hashCode得到该对象的哈希码,然后根据哈希码计算出该对象插入到集合中的位置。

  1. import java.util.*;
  2. public class HashSetTest01 {
  3. public static void main(String[] args) {
  4. //它是无序的,不重复
  5. Set set = new HashSet();
  6. set.add("a");
  7. set.add("b");
  8. set.add("c");
  9. //输出是无序的
  10. for (Iterator iter=set.iterator(); iter.hasNext();) {
  11. System.out.println(iter.next());
  12. }
  13. //加入重复数据
  14. set.add("a");
  15. System.out.println("");
  16. for (Iterator iter=set.iterator(); iter.hasNext();) {
  17. System.out.println(iter.next());
  18. }
  19. String s1 = "abc";
  20. String s2 = "abc";
  21. System.out.println("s1 equals s2 ," + s1.equals(s2));
  22. //equals相等,hashcode一定是相等的
  23. System.out.println("s1.hashCode=" + s1.hashCode());
  24. System.out.println("s2.hashCode=" + s2.hashCode());
  25. String s3 = "ddddd";
  26. System.out.println("s1 equlas s3," + s1.equals(s3));
  27. System.out.println("s3.hashCode=" + s3.hashCode());
  28. }
  29. }

1.4.3、equals和hashCode

  1. import java.util.*;
  2. public class HashSetTest02 {
  3. public static void main(String[] args) {
  4. Person p1 = new Person();
  5. p1.name = "张三";
  6. p1.age = 20;
  7. Person p2 = new Person();
  8. p2.name = "李四";
  9. p2.age = 30;
  10. Person p3 = new Person();
  11. p3.name = "张三";
  12. p3.age = 40;
  13. Set set = new HashSet();
  14. set.add(p1);
  15. set.add(p2);
  16. set.add(p3);
  17. for (Iterator iter=set.iterator(); iter.hasNext();) {
  18. Person p = (Person)iter.next();
  19. System.out.println("name=" + p.name + ", age=" + p.age);
  20. }
  21. System.out.println("p1.hashCode=" + p1.hashCode());
  22. System.out.println("p2.hashCode=" + p2.hashCode());
  23. System.out.println("p3.hashCode=" + p3.hashCode());
  24. }
  25. }
  26. class Person {
  27. String name;
  28. int age;
  29. }

加入了重复的数据,因为hashCode是不同的,所以会根据算出不同的位置,存储格式

Person{张三,20} Person{李四,30} Person{张三,40}
7699183 14285251 10267414

进一步完善,覆盖equals

  1. import java.util.*;
  2. public class HashSetTest03 {
  3. public static void main(String[] args) {
  4. Person p1 = new Person();
  5. p1.name = "张三";
  6. p1.age = 20;
  7. Person p2 = new Person();
  8. p2.name = "李四";
  9. p2.age = 30;
  10. Person p3 = new Person();
  11. p3.name = "张三";
  12. p3.age = 40;
  13. System.out.println("p1 equals p2," + p1.equals(p2));
  14. System.out.println("p1 equals p3," + p1.equals(p3));
  15. Set set = new HashSet();
  16. set.add(p1);
  17. set.add(p2);
  18. set.add(p3);
  19. for (Iterator iter=set.iterator(); iter.hasNext();) {
  20. Person p = (Person)iter.next();
  21. System.out.println("name=" + p.name + ", age=" + p.age);
  22. }
  23. System.out.println("p1.hashCode=" + p1.hashCode());
  24. System.out.println("p2.hashCode=" + p2.hashCode());
  25. System.out.println("p3.hashCode=" + p3.hashCode());
  26. }
  27. }
  28. class Person {
  29. String name;
  30. int age;
  31. //覆盖equals
  32. public boolean equals(Object obj) {
  33. if (this == obj) {
  34. return true;
  35. }
  36. if (obj instanceof Person) {
  37. Person p = (Person)obj;
  38. return this.name.equals(p.name);
  39. }
  40. return false;
  41. }
  42. }

以上仍然存在重复数据,在Person中覆盖了hashCode方法,能够正确的比较出两个Person是相等的还是不等的,但是为什么HashSet中还是放入了重复数据?因为Person对象的hashCode不同,所以它就换算出了不同的位置,让后就会把相关的值放到不同的位置上,就忽略equlas,所以我们必须覆盖hashCode方法

Person{张三,20} Person{李四,30} Person{张三,40}
7699183 14285251 10267414

【代码示例】,只覆盖hashCode,不覆盖equals

  1. import java.util.*;
  2. public class HashSetTest04 {
  3. public static void main(String[] args) {
  4. Person p1 = new Person();
  5. p1.name = "张三";
  6. p1.age = 20;
  7. Person p2 = new Person();
  8. p2.name = "李四";
  9. p2.age = 30;
  10. Person p3 = new Person();
  11. p3.name = "张三";
  12. p3.age = 40;
  13. System.out.println("p1 equals p2," + p1.equals(p2));
  14. System.out.println("p1 equals p3," + p1.equals(p3));
  15. Set set = new HashSet();
  16. set.add(p1);
  17. set.add(p2);
  18. set.add(p3);
  19. for (Iterator iter=set.iterator(); iter.hasNext();) {
  20. Person p = (Person)iter.next();
  21. System.out.println("name=" + p.name + ", age=" + p.age);
  22. }
  23. System.out.println("p1.hashCode=" + p1.hashCode());
  24. System.out.println("p2.hashCode=" + p2.hashCode());
  25. System.out.println("p3.hashCode=" + p3.hashCode());
  26. }
  27. }
  28. class Person {
  29. String name;
  30. int age;
  31. //覆盖hashCode
  32. public int hashCode() {
  33. return (name==null)?0:name.hashCode();
  34. }
  35. }

以上示例,张三的hashCode相同,当两个对象的equals不同,所以认为值是以不一样的,那么java会随机换算出一个新的位置,放重复数据

Person{张三,20} Person{李四,30} Person{张三,40}
774889-1 14285251 774889-2

【代码示例】,进一步改善,覆盖equals,覆盖hashCode

  1. import java.util.*;
  2. public class HashSetTest05 {
  3. public static void main(String[] args) {
  4. Person p1 = new Person();
  5. p1.name = "张三";
  6. p1.age = 20;
  7. Person p2 = new Person();
  8. p2.name = "李四";
  9. p2.age = 30;
  10. Person p3 = new Person();
  11. p3.name = "张三";
  12. p3.age = 40;
  13. System.out.println("p1 equals p2," + p1.equals(p2));
  14. System.out.println("p1 equals p3," + p1.equals(p3));
  15. Set set = new HashSet();
  16. set.add(p1);
  17. set.add(p2);
  18. set.add(p3);
  19. for (Iterator iter=set.iterator(); iter.hasNext();) {
  20. Person p = (Person)iter.next();
  21. System.out.println("name=" + p.name + ", age=" + p.age);
  22. }
  23. System.out.println("p1.hashCode=" + p1.hashCode());
  24. System.out.println("p2.hashCode=" + p2.hashCode());
  25. System.out.println("p3.hashCode=" + p3.hashCode());
  26. }
  27. }
  28. class Person {
  29. String name;
  30. int age;
  31. //覆盖hashCode
  32. public int hashCode() {
  33. return (name==null)?0:name.hashCode();
  34. }
  35. //覆盖equals
  36. public boolean equals(Object obj) {
  37. if (this == obj) {
  38. return true;
  39. }
  40. if (obj instanceof Person) {
  41. Person p = (Person)obj;
  42. return this.name.equals(p.name);
  43. }
  44. return false;
  45. }
  46. }

以上输出完全正确的,因为覆盖了equals和hashCode,当hashCode相同,它会调用equals进行比较,如果equals比较相等将不加把此元素加入到Set中,但equals比较不相等会重新根据hashCode换算位置仍然会将该元素加入进去的。

Person{张三,20} Person{李四,30}
774889 842061

注意:特别是向HashSet或HashMap中加入数据时必须同时覆盖equals和hashCode方法,应该养成一种习惯覆盖equals的同时最好同时覆盖hashCode

Java要求:
两个对象equals相等,那么它的hashcode相等
两个对象equals不相等,那么它的hashcode并不要求它不相等,但一般建议不相等
hashcode相等不代表两个对象相等(采用equals比较)

1.4.4、TreeSet

TreeSet可以对Set集合进行排序,默认自然排序(即升序),但也可以做客户化的排序

  1. import java.util.*;
  2. public class TreeSetTest01 {
  3. public static void main(String[] args) {
  4. Set set = new TreeSet();
  5. set.add(9);
  6. set.add(2);
  7. set.add(5);
  8. set.add(1);
  9. //不能放入重复数据
  10. set.add(5);
  11. for (Iterator iter=set.iterator(); iter.hasNext();) {
  12. Integer v = (Integer)iter.next();
  13. System.out.println(v);
  14. }
  15. }
  16. }

以上没有输出重复的,是按自然顺序排序的(升序)

  1. import java.util.*;
  2. public class TreeSetTest02 {
  3. public static void main(String[] args) {
  4. Set set = new TreeSet();
  5. set.add(9);
  6. set.add(2);
  7. set.add(5);
  8. set.add(1);
  9. //不能放入重复数据
  10. set.add(5);
  11. //不能加入abc,加入后无法排序
  12. //排序只能对一种类型排序
  13. //set.add("abc");
  14. for (Iterator iter=set.iterator(); iter.hasNext();) {
  15. //Integer v = (Integer)iter.next();
  16. //System.out.println(v);
  17. System.out.println(iter.next());
  18. }
  19. }
  20. }

【代码示例】,对Person进行自然排序

  1. import java.util.*;
  2. public class TreeSetTest03 {
  3. public static void main(String[] args) {
  4. Person p1 = new Person();
  5. p1.name = "张三";
  6. p1.age = 20;
  7. Person p2 = new Person();
  8. p2.name = "李四";
  9. p2.age = 30;
  10. Person p3 = new Person();
  11. p3.name = "张三";
  12. p3.age = 40;
  13. Set set = new TreeSet();
  14. set.add(p1);
  15. set.add(p2);
  16. set.add(p3);
  17. for (Iterator iter=set.iterator(); iter.hasNext();) {
  18. Person p = (Person)iter.next();
  19. System.out.println("name=" + p.name + ", age=" + p.age);
  20. }
  21. }
  22. }
  23. class Person {
  24. String name;
  25. int age;
  26. }

出现错误,因为放到TreeSet中TreeSet会对其进行排序,那么必须实现Comparable接口,而我们的Person没有实现,所以出现了错误,如:基本类型的包装类和String他们都是可以排序的,他们都实现Comparable接口

1.4.5、实现Comparable接口完成排序

  1. import java.util.*;
  2. public class TreeSetTest04 {
  3. public static void main(String[] args) {
  4. Person p1 = new Person();
  5. p1.name = "张三";
  6. p1.age = 20;
  7. Person p3 = new Person();
  8. p3.name = "张三";
  9. p3.age = 40;
  10. Person p2 = new Person();
  11. p2.name = "李四";
  12. p2.age = 30;
  13. Set set = new TreeSet();
  14. set.add(p1);
  15. set.add(p2);
  16. set.add(p3);
  17. for (Iterator iter=set.iterator(); iter.hasNext();) {
  18. Person p = (Person)iter.next();
  19. System.out.println("name=" + p.name + ", age=" + p.age);
  20. }
  21. }
  22. }
  23. class Person implements Comparable {
  24. String name;
  25. int age;
  26. //如果覆盖了equals,最好保证equals和compareto在
  27. //相等情况下的比较规则是一致的
  28. public int compareTo(Object o) {
  29. if (o instanceof Person) {
  30. Person p = (Person)o;
  31. //升序
  32. //return (this.age - p.age);
  33. //降序
  34. return (p.age-this.age);
  35. }
  36. throw new IllegalArgumentException("非法参数,o=" + o);
  37. }
  38. }

1.4.6、实现Comparator接口完成排序

  1. import java.util.*;
  2. public class TreeSetTest05 {
  3. public static void main(String[] args) {
  4. Person p1 = new Person();
  5. p1.name = "张三";
  6. p1.age = 20;
  7. Person p3 = new Person();
  8. p3.name = "张三";
  9. p3.age = 40;
  10. Person p2 = new Person();
  11. p2.name = "李四";
  12. p2.age = 30;
  13. Comparator personComparator = new PersonComparator();
  14. Set set = new TreeSet(personComparator);
  15. set.add(p1);
  16. set.add(p2);
  17. set.add(p3);
  18. for (Iterator iter=set.iterator(); iter.hasNext();) {
  19. Person p = (Person)iter.next();
  20. System.out.println("name=" + p.name + ", age=" + p.age);
  21. }
  22. }
  23. }
  24. class Person {
  25. String name;
  26. int age;
  27. }
  28. //实现Person的比较器
  29. //Comparator和Comparable的区别?
  30. //Comparable是默认的比较接口,Comparable和需要比较的对象紧密结合到一起了
  31. //Comparator可以分离比较规则,所以它更具灵活性
  32. class PersonComparator implements Comparator {
  33. public int compare(Object o1, Object o2) {
  34. if (!(o1 instanceof Person)) {
  35. throw new IllegalArgumentException("非法参数,o1=" + o1);
  36. }
  37. if (!(o2 instanceof Person)) {
  38. throw new IllegalArgumentException("非法参数,o2=" + o2);
  39. }
  40. Person p1 = (Person)o1;
  41. Person p2 = (Person)o2;
  42. return p1.age - p2.age;
  43. }
  44. }

1.4.7、采用匿名类完成Comparator的实现

  1. import java.util.*;
  2. public class TreeSetTest06 {
  3. public static void main(String[] args) {
  4. Person p1 = new Person();
  5. p1.name = "张三";
  6. p1.age = 20;
  7. Person p3 = new Person();
  8. p3.name = "张三";
  9. p3.age = 40;
  10. Person p2 = new Person();
  11. p2.name = "李四";
  12. p2.age = 30;
  13. //采用匿名类实现比较器
  14. Set set = new TreeSet(new Comparator() {
  15. public int compare(Object o1, Object o2) {
  16. if (!(o1 instanceof Person)) {
  17. throw new IllegalArgumentException("非法参数,o1=" + o1);
  18. }
  19. if (!(o2 instanceof Person)) {
  20. throw new IllegalArgumentException("非法参数,o2=" + o2);
  21. }
  22. Person p1 = (Person)o1;
  23. Person p2 = (Person)o2;
  24. return p1.age - p2.age;
  25. }
  26. });
  27. set.add(p1);
  28. set.add(p2);
  29. set.add(p3);
  30. for (Iterator iter=set.iterator(); iter.hasNext();) {
  31. Person p = (Person)iter.next();
  32. System.out.println("name=" + p.name + ", age=" + p.age);
  33. }
  34. }
  35. }
  36. class Person {
  37. String name;
  38. int age;
  39. }

1.4.8、Comparable和Comparator的区别?

一个类实现了Camparable接口则表明这个类的对象之间是可以相互比较的,这个类对象组成的集合就可以直接使用sort方法排序。
Comparator可以看成一种算法的实现,将算法和数据分离,Comparator也可以在下面两种环境下使用:
1、类的没有考虑到比较问题而没有实现Comparable,可以通过Comparator来实现排序而不必改变对象本身
2、可以使用多种排序标准,比如升序、降序等
而 Comparator 是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较。

可以说一个是自已完成比较,一个是外部程序实现比较的差别而已。

用Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。

1.5、Map接口

Map中可以放置键值对,也就是每一个元素都包含键对象和值对象,Map实现较常用的为HashMap,HashMap对键对象的存取和HashSet一样,仍然采用的是哈希算法,所以如果使用自定类作为Map的键对象,必须复写equals和hashCode方法。

1.5.1、HashMap

  1. import java.util.*;
  2. public class HashMapTest01 {
  3. public static void main(String[] args) {
  4. Map map = new HashMap();
  5. map.put("1001", "张三");
  6. map.put("1002", "李四");
  7. map.put("1003", "王五");
  8. //采用entrySet遍历Map
  9. Set entrySet = map.entrySet();
  10. for (Iterator iter=entrySet.iterator(); iter.hasNext();) {
  11. Map.Entry entry = (Map.Entry)iter.next();
  12. System.out.println(entry.getKey() + ", " + entry.getValue());
  13. }
  14. System.out.println("");
  15. //取得map中指定的key
  16. Object v = map.get("1003");
  17. System.out.println("1003==" + v);
  18. System.out.println("");
  19. //如果存在相同的条目,会采用此条目替换
  20. //但map中始终保持的是不重复的数据
  21. //主要依靠key开判断是否重复,和value没有任何关系
  22. map.put("1003", "赵柳");
  23. //采用keySet和get取得map中的所有数据
  24. for (Iterator iter=map.keySet().iterator(); iter.hasNext();) {
  25. String k = (String)iter.next();
  26. System.out.println(k + ", " + map.get(k));
  27. }
  28. }
  29. }

1.5.2、HashMap,采用自定义类作为key

  1. import java.util.*;
  2. public class HashMapTest02 {
  3. public static void main(String[] args) {
  4. IdCard idCard1 = new IdCard();
  5. idCard1.cardNo = 223243244243243L;
  6. Person person1 = new Person();
  7. person1.name = "张三";
  8. IdCard idCard2 = new IdCard();
  9. idCard2.cardNo = 223243244244343L;
  10. Person person2 = new Person();
  11. person2.name = "李四";
  12. IdCard idCard3 = new IdCard();
  13. idCard3.cardNo = 223243244243243L;
  14. Person person3 = new Person();
  15. person3.name = "张三";
  16. Map map = new HashMap();
  17. map.put(idCard1, person1);
  18. map.put(idCard2, person2);
  19. map.put(idCard3, person3);
  20. for (Iterator iter=map.entrySet().iterator(); iter.hasNext();) {
  21. Map.Entry entry = (Map.Entry)iter.next();
  22. IdCard idCard = (IdCard)entry.getKey();
  23. Person person = (Person)entry.getValue();
  24. System.out.println(idCard.cardNo + ", " + person.name);
  25. }
  26. }
  27. }
  28. class IdCard {
  29. long cardNo;
  30. //.........
  31. }
  32. class Person {
  33. String name;
  34. }

加入了重复的数据,因为HashMap的底层实现采用的是hash表,所以Map的key必须覆盖hashcode和equals方法

1.5.3、HashMap,覆盖IdCard的equals和hashCode方法

  1. import java.util.*;
  2. public class HashMapTest03 {
  3. public static void main(String[] args) {
  4. IdCard idCard1 = new IdCard();
  5. idCard1.cardNo = 223243244243243L;
  6. Person person1 = new Person();
  7. person1.name = "张三";
  8. IdCard idCard2 = new IdCard();
  9. idCard2.cardNo = 223243244244343L;
  10. Person person2 = new Person();
  11. person2.name = "李四";
  12. IdCard idCard3 = new IdCard();
  13. idCard3.cardNo = 223243244243243L;
  14. Person person3 = new Person();
  15. person3.name = "张三";
  16. Map map = new HashMap();
  17. map.put(idCard1, person1);
  18. map.put(idCard2, person2);
  19. map.put(idCard3, person3);
  20. for (Iterator iter=map.entrySet().iterator(); iter.hasNext();) {
  21. Map.Entry entry = (Map.Entry)iter.next();
  22. IdCard idCard = (IdCard)entry.getKey();
  23. Person person = (Person)entry.getValue();
  24. System.out.println(idCard.cardNo + ", " + person.name);
  25. }
  26. }
  27. }
  28. class IdCard {
  29. long cardNo;
  30. //.........
  31. public boolean equals(Object obj) {
  32. if (obj == this) {
  33. return true;
  34. }
  35. if (obj instanceof IdCard) {
  36. IdCard idCard = (IdCard)obj;
  37. if (this.cardNo == idCard.cardNo) {
  38. return true;
  39. }
  40. }
  41. return false;
  42. }
  43. public int hashCode() {
  44. return new Long(cardNo).hashCode();
  45. }
  46. }
  47. class Person {
  48. String name;
  49. }

以上没有加入重复的数据,因为覆盖了equals和hashCode方法

1.5.4、TreeMap

treeMap可以对Map中的key进行排序,如果map中的key采用的是自定类那么需要实现Comaprable或Comparator接口完成排序

  1. import java.util.*;
  2. public class TreeMapTest01 {
  3. public static void main(String[] args) {
  4. Map map = new TreeMap();
  5. map.put("1003", "王五");
  6. map.put("1001", "张三");
  7. map.put("1002", "李四");
  8. for (Iterator iter=map.entrySet().iterator(); iter.hasNext();) {
  9. Map.Entry entry = (Map.Entry)iter.next();
  10. System.out.println(entry.getKey() + ", " + entry.getValue());
  11. }
  12. }
  13. }

1.6、Collections工具类

Collections位于java.util包中,提供了一系列实用的方法,如:对集合排序,对集合中的内容查找等

  1. import java.util.*;
  2. public class CollectionsTest01 {
  3. public static void main(String[] args) {
  4. List l = new ArrayList();
  5. l.add(5);
  6. l.add(1);
  7. l.add(4);
  8. l.add(2);
  9. for (Iterator iter=l.iterator(); iter.hasNext();) {
  10. System.out.println(iter.next());
  11. }
  12. System.out.println("");
  13. Collections.sort(l);
  14. for (Iterator iter=l.iterator(); iter.hasNext();) {
  15. System.out.println(iter.next());
  16. }
  17. System.out.println("");
  18. Set set = new HashSet();
  19. set.add(10);
  20. set.add(1);
  21. set.add(4);
  22. set.add(9);
  23. //不能直接对set排序
  24. //Collections.sort(set);
  25. List setList = new ArrayList(set);
  26. Collections.sort(setList);
  27. for (Iterator iter=setList.iterator(); iter.hasNext();) {
  28. System.out.println(iter.next());
  29. }
  30. System.out.println("");
  31. int index = Collections.binarySearch(setList, 9);
  32. System.out.println("index=" + index);
  33. System.out.println("");
  34. Collections.reverse(setList);
  35. for (Iterator iter=setList.iterator(); iter.hasNext();) {
  36. System.out.println(iter.next());
  37. }
  38. }
  39. }