Java集合框架中的Set集合及其子类(HashSet,LinkedHashSet,TreeSet)

public interface Set extends Collection
   首先它是一个不包含重复元素的collection,更确切地将,set不满足包含e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个null元素。
   在所有构造方法以及 add、equals 和 hashCode 方法的协定上,Set 接口还加入了其他规定,这些规定超出了从 Collection 接口所继承的内容。
set集合基础:

  • 实现了collection接口
  • set接口的特性:无序的,元素不可重复
  • 底层大多数是Map结构的实现
  • 常用的三个子类都是非同步的

set接口下面的三个常用子类:

  • HashSet(非同步)
  • LinkedHashSet(非同步)
  • TreeSet(非同步)

set中的常用方法

  • add(E e) 如果 set 中尚未存在指定的元素,则添加此元素
  • contains(Object o) 如果 set 包含指定的元素,则返回 true
  • iterator() 返回在此 set 中的元素上进行迭代的迭代器。
  • size() 返回 set 中的元素数(其容量)。
  • toArray() 返回一个包含 set 中所有元素的数组
  • remove(Object o) 如果 set 中存在指定的元素,则将其移除
  • equals(Object o) 比较指定对象与此 set 的相等性

一.HashSet

  • HashSet元素唯一,无序(存取顺序不一致)
  • HashSet底层数据结构是哈希表(哈希表:是元素为链表的数组,具有链表和数组的特点,JDK1.7之前。JDK1.8数组链表和二叉树)
  • 构造一个新的set,其底层HashMap实例的默认初始容量为16,加载因子为0.75
  • HashSet底层是用HashMap来存储的

  当给HashSet集合中存放一个元素时,HashSet会调用该对象的HashCode()方法,来获得该对象的的HashCode值。然后根据HashCode的值决定该对象在HashSet中存放的位置。
  因此在在HashSet中判断两个元素是否相等首先判断两个对象的HashCode值是否相等,然后再判断两个对象的equals()方法的返回值是否相等,只有当这两个都相等的时候才可以说明这两个对象相等。
  总的来说HashSet保证元素唯一性是靠元素重写HashCode()和equals()方法来保证的。
二.LinkedHashSet

  • 底层数据结构是由哈希表(是一个元素为链表的数组)和双向链表组成。该链表定义了迭代顺序保证元素有序,哈希表保证元素唯一
  • 元素有序且唯一(存取顺序一致)
  • 元素可以为null
  • 实际上就是LInkHashMap
import java.util.LinkedHashSet;

public class MyTest2 {
    public static void main(String[] args) {
        LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add(1);
        linkedHashSet.add(4);
        linkedHashSet.add(6);
        //重复的对象不会再次存储
        linkedHashSet.add(6);
        linkedHashSet.add(9);
        //存取顺序一致
        for (Integer integer : linkedHashSet) {
            System.out.println(integer);
        }
    }
}

运行结果为:

1
4
6
9

三.TreeSet

  • TreeSet底层数据结构是红黑树,最大的特点是能够对元素进行排序。
  • 元素唯一可以排序
  • TreeSet元素保证唯一性是靠CompareTo方法的返回值来确定,如果返回为0,就是两个元素相等就不重复存储。
  • 元素不能为空

TreeSet有两种排序方式

  • 自然排序(使用空参构造用自然排序)
  • 使用比较器排序(使用有参构造用比较器排序)
    注意:使用TreeSet集合进行元素的自然排序,那么这个元素必须实现Comparable接口,否则无法进行自然排序。

例一 .使用空参构造,对自己定义的学生对象按照年龄进行排序

//Student类
public class Student implements Comparable<Student>{
    private  String name;
    private int age;
    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public int compareTo(Student s) {
        int num = this.age - s.age;
        //年龄相等,不一定就是同一个人还得比较名字
        int num2 = num==0?this.name.compareTo(s.name):num;
        return num2;
    }
}

import java.util.TreeSet;

public class MyTest {
    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<>();
        treeSet.add(new Student("海绵宝宝",21));
        treeSet.add(new Student("派大星",29));
        treeSet.add(new Student("珊迪",25));
        treeSet.add(new Student("蟹老板",27));
        treeSet.add(new Student("海绵宝宝",24));
        for (Student student : treeSet) {
            System.out.println(student.getAge()+" "+student.getName());
        }
    }
}

运行结果为:

21 海绵宝宝
24 海绵宝宝
25 珊迪
27 蟹老板
29 派大星


例二.使用有参构造,对自己定义的学生对象按照名字进行排序

public class Student {
    private  String name;
    private int age;
    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

import java.util.Comparator;
import java.util.TreeSet;

public class MyTest {
    public static void main(String[] args) {
        //按照名字排序
        Comparator<Student> comparator = new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int num1 = s1.getName().length() - s2.getName().length();
                int num2=num1==0?s1.getName().compareTo(s2.getName()):num1;
                int num3=num2==0?s1.getAge()-s2.getAge():num2;
                return num3;
            }
        };
        TreeSet<Student> treeSet = new TreeSet<>(comparator);
        treeSet.add(new Student("海绵宝宝",21));
        treeSet.add(new Student("派大星",29));
        treeSet.add(new Student("珊迪",25));
        treeSet.add(new Student("蟹老板",27));
        treeSet.add(new Student("海绵宝宝",24));
        for (Student student : treeSet) {
            System.out.println(student.getAge()+" "+student.getName());
        }
    }
}


运行结果为:

25 珊迪
29 派大星
27 蟹老板
21 海绵宝宝
24 海绵宝宝

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值