摘要:本文将带你了解Java语言之集合框架Set,希望本文对大家学JAVA有所帮助。
集合框架 Set的特点:无序,不可以重复元素。
(1)HashSet:数据结构是哈希表。线程是非同步的。
保证元素唯一性的原理:判断元素的hashCode值是否相同。
如果相同,还会继续判断元素的equals方法,是否为true。
(2)TreeSet:可以对Set集合中的元素进行排序。
底层数据结构是二叉树。
保证元素唯一性的依据:compareTo方法return 0。
一、HashSet相关知识
HashSet中的元素不可以重复,如果重复添加,则只会显示一个。
原理如下:
HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
HashSet是如何保证元素唯一性的呢?
答:是通过元素的两个方法,hashCode和equals来完成。
如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashcode值不同,不会调用equals。
*******对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法**********
代码1:
[java] view plain copy 1. package com.package2; 2. 3. import java.util.*; 4. 5. public class HashSet222 6. { 7. 8. public static void main(String[] args) 9. { 10. 11. HashSet hs = new HashSet(); 12. 13. hs.add("java01"); 14. hs.add("java01"); 15. hs.add("java02"); 16. hs.add("java03"); 17. hs.add("java03"); 18. hs.add("java04"); 19. 20. Iterator it = hs.iterator(); 21. 22. while(it.hasNext()) 23. { 24. System.out.println(it.next()); 25. } 26. } 27. } 此demo将String类型的字符串添加进去,并且没有重复,结果如下: java04java02java03java01 由此我们可以断定,String类已经实现了hashcode()方法和equals()方法。打开,帮助文档,确实(这不是废话么^_^) 但是,如果我们要将自定义的元素add进HashSet中,则必须定义其自己的hashcode()方法和equals()方法。如下所示: 代码2: [java] view plain copy 1. package com.package2; 2. import java.util.*; 3. public class HashSet3 4. { 5. public static void main(String[] args) 6. { 7. HashSet hs = new HashSet(); 8. 9. hs.add(new Person("a1",11)); 10. hs.add(new Person("a2",12)); 11. hs.add(new Person("a3",13)); 12. hs.add(new Person("a2",12)); 13. hs.add(new Person("a4",14)); 14. 15. 16. Iterator it = hs.iterator(); 17. 18. while(it.hasNext()) 19. { 20. Person p = (Person)it.next(); 21. System.out.println(p.getName()+"::"+p.getAge()); 22. } 23. } 24. } 25. class Person 26. { 27. private String name; 28. private int age; 29. Person(String name,int age) 30. { 31. this.name = name; 32. this.age = age; 33. } 34. 35. public int hashCode() 36. { 37. System.out.println(this.name+"....hashCode"); 38. return name.hashCode()+age*37; //保证此元素的返回值尽量不一致。 39. } 40. 41. public boolean equals(Object obj) 42. { 43. 44. if(!(obj instanceof Person)) 45. return false; 46. 47. Person p = (Person)obj; 48. System.out.println(this.name+"...equals.."+p.name); 49. 50. return this.name.equals(p.name) && this.age == p.age; 51. } 52. 53. 54. public String getName() 55. { 56. return name; 57. } 58. public int getAge() 59. { 60. return age; 61. } 62. } 输出结果如下: a1....hashCodea2....hashCodea3....hashCodea2....hashCodea2...equals..a2a4....hashCodea1::11a3::13a2::12a4::14 由此可以看出,将元素add时,会首先调用元素的hashcode()方法,当返回值重复时,会调用其equals方法。缺少任何一种方法都构不成一个HashSet集合。 二、TreeSet相关知识 TreeSet有俩种排序方式。 TreeSet排序的第一种方式:让元素自身具备比较性。步骤:将add进TreeSet中的元素实现Comparable接口,并且覆盖compareTo方法。这种顺序也是元素的自然顺序,或者叫做默认顺序。 TreeSet的第二种排序方式。当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性(即利用其另一种构造函数建立对象)。在集合初始化时,就有了比较方式。 步骤:利用某个指定类实现Comparator接口,并且覆盖compare()方法,则此类会成为一个具备比较方法的类。在建立TreeSet的时候,将此类对象传入其中。 则此时,添加进TreeSet中的元素可按照指定比较方法进行排序。 下边举例演示俩种排序方式。 排序方式一:代码1: [java] view plain copy 1. package com.package1; 2. 3. import java.util.*; 4. 5. public class TreeSettest { 6. 7. public static void main(String[] args) { 8. //创建对象 9. TreeSet ts=new TreeSet(); 10. 11. //添加元素 12. ts.add("abcjjj"); 13. ts.add("abb"); 14. ts.add("daccc"); 15. ts.add("gfg"); 16. ts.add("geee"); 17. ts.add("r"); 18. 19. //进行迭代 20. Iterator it=ts.iterator(); 21. 22. //循环取出元素 23. while(it.hasNext()) 24. { 25. System.out.println(it.next()); 26. } 27. 28. } 29. 30. } 输出结果如下: abbabcjjjdacccgeeegfgr 由此可见,此时元素具备可比性,即按照其自然顺序进行排序。打开帮助文档,我们可以清晰的发现String已经实现了Comparable接口,并且已经覆盖了compareTo(),“这不是废话么^_^”,如图所示: ps……如果我们要往TreeSet里添加的元素是自己刚刚定义的,我们也可以自己定义该元素的类实现Comparable接口,并且覆盖compareTo()方法,如下所示:代码2: [java] view plain copy 1. package com.package1; 2. 3. import java.util.*; 4. 5. class Student implements Comparable//该接口强制让学生具备比较性。 6. { 7. private String name; 8. private int age; 9. 10. Student(String name,int age) 11. { 12. this.name = name; 13. this.age = age; 14. } 15. 16. public int compareTo(Object obj) 17. { 18. 19. //return 0; 20. 21. if(!(obj instanceof Student)) 22. throw new RuntimeException("不是学生对象"); 23. Student s = (Student)obj; 24. 25. //System.out.println(this.name+"....compareto....."+s.name); 26. if(this.age>s.age) 27. return 1; 28. if(this.age==s.age) 29. { 30. return this.name.compareTo(s.name); 31. } 32. return -1; 33. /**/ 34. } 35. 36. public String getName() 37. { 38. return name; 39. 40. } 41. public int getAge() 42. { 43. return age; 44. } 45. } 46. public class TreeSet2 47. { 48. public static void main(String[] args) 49. { 50. TreeSet ts = new TreeSet(); 51. 52. ts.add(new Student("lisi02",22)); 53. ts.add(new Student("lisi02",21)); 54. ts.add(new Student("lisi007",20)); 55. ts.add(new Student("lisi09",19)); 56. ts.add(new Student("lisi06",18)); 57. ts.add(new Student("lisi06",18)); 58. ts.add(new Student("lisi007",29)); 59. //ts.add(new Student("lisi007",20)); 60. //ts.add(new Student("lisi01",40)); 61. 62. Iterator it = ts.iterator(); 63. while(it.hasNext()) 64. { 65. Student stu = (Student)it.next(); 66. System.out.println(stu.getName()+"..."+stu.getAge()); 67. } 68. } 69. } 结果如下: lisi06...18lisi09...19lisi007...20lisi02...21lisi02...22lisi007...29 此例子将学生元素,强行按照年龄来排序,这就是我们想要的排序方式。 第二种排序如下: 还是刚刚代码1的例子,我们使用第二种排序方式,使得String类型的元素按照长度来排序。 代码3: [java] view plain copy 1. /* 2. * 使元素按照长度来排序,若长度相同,则按照自然排序。 3. */ 4. public class TreeSettest { 5. 6. public static void main(String[] args) { 7. //创建对象 8. TreeSet ts=new TreeSet(new MyCompare()); 9. 10. //添加元素 11. ts.add("abc"); 12. ts.add("bcc"); 13. ts.add("das"); 14. ts.add("bcde"); 15. ts.add("asdfg"); 16. ts.add("befqfca"); 17. 18. //进行迭代 19. Iterator it=ts.iterator(); 20. 21. //循环取出元素 22. while(it.hasNext()) 23. { 24. System.out.println(it.next()); 25. } 26. 27. } 28. 29. } 30. 31. //定义一个类实现Comparator接口,并且覆盖compare()方法。 32. class MyCompare implements Comparator 33. { 34. 35. @Override 36. public int compare(Object o1, Object o2) { 37. //进行强制类型转换 38. String s1=(String) o1; 39. String s2=(String) o2; 40. 41. //进行比较 42. if(s1.length()>s2.length()) 43. return 1; 44. if(s1.length()<s2.length()) 45. return -1; 46. if(s1.length()==s2.length()) 47. { 48. return s1.compareTo(s2); 49. } 50. return 0; 51. } 52. }
结果如下:
abc
bcc
das
bcde
asdfg
befqfca
此种情况下,我们不方便修改源代码,而只需要修改比较方法时,我们就可以自己创建一个比较器。在建立TreeSet时,将比较器传入即可使元素按照特定比较方式输出。
总结:
Comparable(方式一)接口和Compartor(方式二)接口的比较:
两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但
是需要修改源代码。
用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把
比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其
可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。
以上就介绍了JAVA的相关知识,希望对JAVA有兴趣的朋友有所帮助。了解更多内容,请关注职坐标编程语言JAVA频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号