当前位置:   article > 正文

【JAVA学习之路 | 进阶篇】Set及其实现类与常用方法_set的实现类

set的实现类

1.Set及其常用实现类

Set接口是java.util.Collection接口的子接口.用来存储一个一个的数据.后面学习到的Map接口则用来存储key-value键值对.

  1. Set : 存储无序的,不可重复的数据
  2. |----->HashSet : 主要实现类 : 底层使用的是HashMap,即使用数组+单向链表+红黑树来存储。
  3. |----->LinkedSet : 是HashSet的子类,在其存储结构的基础上,增加了一组双向链表,用来记录添加
  4. 元素的先后顺序。即我们可以按照添加的顺序实现遍历.便于频繁查询工作。
  5. |----->TreeSet : 底层使用红黑树进行存储,可以按照添加的元素的指定属性的大小顺序来进行遍历.

2.Set中常用方法

即Collection接口中的15个抽象方法.没有新增的方法.

e6c69ba4ae7a4a50901c8cde6a5030f4.png

3.Set中无序性与不可重复性的理解

(1). 无序性 :并不等同于随机性.

添加元素的顺序与遍历元素的顺序不一致,是否能说明Set的无序性呢?其实是不可以的.因为可以看到,多次运行,遍历结果还是第一次的遍历元素的顺序.

  1. @Test
  2. public void Test1() {
  3. Set set = new HashSet();
  4. //自动装箱
  5. set.add(12);
  6. set.add(34);
  7. set.add("hexua");
  8. set.add('a');
  9. //foreach循环
  10. for (Object obj : set) {
  11. System.out.println(obj);
  12. }
  13. }
  14. 控制台
  15. //多次运行,都是这个顺序
  16. a
  17. 34
  18. 12
  19. hexua

无序性与添加的元素的位置有关.其并不像ArrayList是连续排列的.其是根据哈希函数算得的哈希值计算其在数组中的存储位置,因为该位置不是依次紧密排列的,表现为无序性.(学过数据结构的应该觉得比较好理解一点)

(2). 不可重复性 : 添加到Set元素中的元素不能相同.

其比较的标准是hashCode()得到的哈希值及equals()得到的boolean类型的结果.只有哈希值相等,而且equals()返回true,则判断元素已重复,所以不将该元素添加到Set中.

(3). 注 : 添加到HashSet/LinkedHashSet的元素的要求 : 必须重写Object类中的HashCode与equals方法.且二者需要保持一致性.

4.HashSet的底层结构

通过查看源码,发现HashSet的底层是通过HashMap来实现的.

  1. public HashSet() {
  2. map = new HashMap<>();
  3. }

而HashMap的底层使用数组+单向链表+红黑树来存储.

例如add(12),通过hashCode方法可以算出一个哈希值,并将该元素放到该哈希值对应的位置存储.该位置存储的是元素的地址.接着后面add(23),add(34)...如果hashCode()算得某个位置,并且该位置已经存储了某个元素的地址(哈希冲突),那么第一个元素可以存储第二个元素的引用,从而构成了单链表.

重复性判断可以这样理解.hashCode()算出一个哈希值,找到该哈希值对应的位置,将该元素(A)与该位置对应的元素(B)(只有单元素情况)进行equals比较.如果相等,则返回,不加入到HashSet中,如果不相等,则原来的元素(B)存储该元素(A)的引用,即加入到HashSet中.如果哈希值对应的位置指向的一条单向链表,则将该元素与指向的一条单链表依次比较.

5.TreeSet的使用

(1). 查看源码发现,TreeSet底层是通过TreeMap实现,故TreeSet底层使用红黑树进行存储.

(2). 可以按照添加元素的指定的属性大小的顺序进行遍历.

(3). 要求 : 添加到TreeSet中的元素对象必须是同一类型,否则会报错.添加的元素需要考虑排序.自然排序or定制排序.即实现Comparable接口重写CompareTo方法或者实现Comparator接口重写Compare方法.

(4). 判断数据是否相等的标准.

  • 由于TreeSet并不是由数组+单向链表进行存储,所以不必重写hashCode与equals方法.
  • 标准考虑自然排序或者定制排序.由于TreeSet中不能存在相同的元素,所以后一个相同的元素不能被添加到TreeSet中.

自然排序(Comparable接口实现compareTo方法)以名字作为比较的依据.

  1. public class Person implements Comparable{
  2. private String name;
  3. private int age;
  4. public Person() {
  5. }
  6. public Person(String name, int age) {
  7. this.name = name;
  8. this.age = age;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public int getAge() {
  17. return age;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. @Override
  23. public String toString() {
  24. return "Person{" +
  25. "name='" + name + '\'' +
  26. ", age=" + age +
  27. '}';
  28. }
  29. @Override
  30. public int compareTo(Object o) {
  31. if (o instanceof Person) {
  32. Person p = (Person) o;
  33. return this.getName().compareTo(p.getName());
  34. }
  35. throw new RuntimeException("异常");
  36. }
  37. }
  38. @Test
  39. public void Test2() {
  40. Set set = new TreeSet();
  41. set.add(new Person("mahuateng", 50));
  42. set.add(new Person("dinglei", 51));
  43. set.add(new Person("liuqiangdong", 49));
  44. set.add(new Person("mayun", 52));
  45. for (Object obj : set) {
  46. //默认调用toString方法
  47. System.out.println(obj);
  48. }
  49. }
  50. 控制台
  51. Person{name='dinglei', age=51}
  52. Person{name='liuqiangdong', age=49}
  53. Person{name='mahuateng', age=50}
  54. Person{name='mayun', age=52}

定制排序(Comparator接口实现Compare方法)以名字作为比较的依据.

按住Ctrl+p,查看到可以放比较器实参.

a2a859573ab048eebb4196d684d6c6bf.png

  1. @Test
  2. public void Test2() {
  3. Set set = new TreeSet(new Comparator() {
  4. @Override
  5. public int compare(Object o1, Object o2) {
  6. if (o1 instanceof Person && o2 instanceof Person) {
  7. Person p1 = (Person) o1;
  8. Person p2 = (Person) o2;
  9. return p1.getAge() - p2.getAge();
  10. }
  11. throw new RuntimeException();
  12. }
  13. });
  14. set.add(new Person("mahuateng", 50));
  15. set.add(new Person("dinglei", 51));
  16. set.add(new Person("liuqiangdong", 49));
  17. set.add(new Person("mayun", 52));
  18. for (Object obj : set) {
  19. System.out.println(obj);
  20. }
  21. }
  22. 控制台
  23. Person{name='liuqiangdong', age=49}
  24. Person{name='mahuateng', age=50}
  25. Person{name='dinglei', age=51}
  26. Person{name='mayun', age=52}

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号