扩展Collection接口,是无序集合,不允许存放重复的元素;允许使用null元素,但对 add()、equals() 和 hashCode() 方法添加了限制。

特征:有序列表,允许存放重复的元素,通过索引下标进行取值和删除;(是个接口)

1.Set集合下面的实现类

有很多实现类,列举的是比较重要的,开发时用的比较多的

  • HashSet 依靠hash值进行存储的,如果两个元素hash值一样的话,就不再存储了
  • TreeSet 底层是二叉树,对存储数据进行自然排序

2. Set集合下面的方法

package com.jzj.b_homework;
import java.util.HashSet;
import java.util.Set;
//1.定义一个Collection接口类型的变量,引用一个Set集合的实现类,实现添加单个元素,
// 添加另一个集合,删除元素,判断集合中是否包含一个元素,判断是否为空,清除集合,返回集合里元素的个数等常用操作
public class Demo1 {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("三国演义");
        set.add("水浒传");
        set.add("红楼梦");
        set.add("西游记");
        System.out.println(set);//[水浒传, 三国演义, 红楼梦, 西游记]
        Set<String> set1 = new HashSet<>();
        set1.add("张三");
        set1.add("赵四");
        set1.add("王五");
        set1.add("李六");
        set.addAll(set1);
        System.out.println(set);//[水浒传, 张三, 李六, 三国演义, 红楼梦, 西游记, 赵四, 王五]
        set.remove("张三");
        System.out.println(set);//[水浒传, 李六, 三国演义, 红楼梦, 西游记, 赵四, 王五]
        System.out.println(set.contains("三国演义"));//true
        System.out.println(set.isEmpty());//false
        set.clear();
        System.out.println(set);//[]
        System.out.println(set.size());//0
        System.out.println(set1.size());//4
    }
}

3. 遍历List集合的三种方法

  • 增强for循环
  • 迭代器

3.2增强for循环 

package com.jzj.b_homework;
import java.util.HashSet;
import java.util.Set;
//.创建Set接口的实现类,添加10个以上的元素,通过foreach遍历此集合元素
public class Demo3 {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("三国演义");
        set.add("水浒传");
        set.add("红楼梦");
        set.add("西游记");
        set.add("吴承恩");
        set.add("曹雪芹");
        set.add("罗贯中");
        set.add("施耐庵");
        set.add("张三");
        set.add("赵四");
        set.add("王五");
        set.add("李六");
        for (String s : set) {
            System.out.println(s);
        }
    }
}

3.3迭代器

package com.jzj.b_homework;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

//创建Set接口的实现类,添加10个以上的元素,通过Iterator遍历此集合元素
public class Demo2 {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("三国演义");
        set.add("水浒传");
        set.add("红楼梦");
        set.add("西游记");
        set.add("吴承恩");
        set.add("曹雪芹");
        set.add("罗贯中");
        set.add("施耐庵");
        set.add("张三");
        set.add("赵四");
        set.add("王五");
        set.add("李六");
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            String next =  iterator.next();
            System.out.println(next);
        }
    }
}

 4.HashSet

依靠hash值进行存储的,如果两个元素hash值一样的话,就不再存储了

特征:查询慢,增删快

4.1 HashSet存对象

package com.qfedu.b_hashSet;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

class Person {
    int id;
    String name;

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return id == person.id && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Person person1 = new Person(1, "zhangsan");
        Person person2 = new Person(1, "李四");
        Person person3 = new Person(1, "李四");
        Person person4 = new Person(1, "李四");
        Set<Person> set = new HashSet<>();
        //在调用add方法的时候 底层在调用hashCode方法和equals
        set.add(person1);
        set.add(person2);
        set.add(person3);
        set.add(person4);
        System.out.println(set);
        //感觉不太合适,发现存的两个对象的内容是一样。真实开发的时候
        //只关注内容的,如果内容一样,我也让你存不进去。!!!
        //咋办

        //总结:以后set集合中如果想存对象的时候,要求对象的内容如果一样的
        //话,不能存到set集合中,咋办?重写equals方法和hahsCode方法
        //hash值不一样,对象一定不一样。
        //对象一样的话,hash只能一定一样
    }
}

HashSet存对象的时候,一定在类中重写equals和hashCode方法  

5. TreeSet

TreeSet集合是基于TreeMap的实现,而TreeMap是基于二叉树(红黑树)结构,也就是说TreeSet集合的底层使用的二叉树(红黑树)结构。

该实现类也遵循了统一约束:数据的唯一性

所有存储于 TreeSet 中的元素可以使用 Java 里的 Comparator 或者 Comparable 进行排序。

5.1TreeSet存对象

将此对象与指定的对象进行比较以进行排序。 返回一个负整数,零或正整数,因为该对象小于,等于或大于指定对象。

package com.qfedu.c_treeSet;

import java.util.Set;
import java.util.TreeSet;

class Student implements Comparable<Student>{
    String name;
    int age;

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Student o) {
        System.out.println("123");
        int num = this.age - o.age;
        return num;
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Student stu1 = new Student("老邢", 45);
        Student stu2 = new Student("老邢", 35);
        Student stu3 = new Student("saolei", 25);
        Student stu4 = new Student("老万", 87);
        //按照年龄进行排序 存到TreeSet集合中
        Set<Student> set = new TreeSet<>();
        set.add(stu1);
        set.add(stu2);
        set.add(stu3);
        set.add(stu4);
        System.out.println(set);

        //  Exception in thread "main" java.lang.ClassCastException:
        //  com.qfedu.c_treeSet.Student cannot be cast to java.lang.Comparable
        //	at java.util.TreeMap.compare(TreeMap.java:1294)
        //类转换异常的错误,Student转换不了Comparable
        //y因为底层在进行排序的时候,实现了Comparable这个接口
        //为啥泛型String没有报错  Integer也没有报错
    }
}

总结:TreeSet存对象的时候,一定要实现一个接口Comparable,重写compareTo方法 比较两个对象某个属性的int类型差值

5.2TreeSet使用比较器存数据

package com.qfedu.b_comparator;

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

class Student {
    String name;
    int age;

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
class MyComparator implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
        int num = o1.age - o2.age;
        return num;
    }
}
public class Demo1 {
    public static void main(String[] args) {
        //如果想要使用比较器的写法 必须再new TreeSet的时候
        //加上比较器对象
        //TreeSet 有一个有参构造,有参构造的方法是Comparwator的对象
        //Comparator是一个接口 不能实例化,咋办?再写一个类去实现这个接口
        Set<Student> students = new TreeSet<>(new MyComparator());
        students.add(new Student("维一", 23));
        students.add(new Student("永康", 19));
        students.add(new Student("赵娜", 18));
        students.add(new Student("运铎", 28));
        students.add(new Student("佳祥", 36));
        System.out.println(students);
    }
}

总结:

ArrayList就是单纯地add

LinkedList也是单纯地add

HashSet不单纯,需要重写equals和hashCode方法

TreeSet不单出,需要在实现类中实现Comparable接口,让类具有比价排序的功能