Set接口以及三个子类

Set

和List一样同属于Collection接口的子接口,但有区别:
Set:元素不允许重复
List:元素允许重复

Set的三个子类

在这里插入图片描述

HashSet

  1. 元素唯一且无序
    HashSet之所以能保证唯一性,是靠重写HashCode方和和equals方法
    重写HashCode是为了优化次数,减少调用equals的次数
package org.org.westos.demo;

import java.util.HashSet;

public class MyClass {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("aaa");
        set.add("bbb");
        set.add("ccc");
        set.add("ddd");
        //添加两个重复元素
        set.add("ddd");
        set.add("ccc");
        //新式for循环遍历
        for (String s : set) {
            System.out.println(s);
        }
    }
}

在这里插入图片描述
看得出来,输出的内容不会有重复,且输出的顺序与存储的顺序不一致,这就是HashSet集合的特点,另外,HashSet集合底层用的是HashMap集合来存储的,HashMap下一章会讲

LinkedHashSet

  1. 元素唯一且有序,底层数据结构哈希表保证元素唯一,链表保证元素有序
package org.org.westos.demo;

import java.util.LinkedHashSet;

public class MyClass {
    public static void main(String[] args) {
        LinkedHashSet<Integer> set = new LinkedHashSet<>();
        set.add(100);
        set.add(300);
        set.add(400);
        set.add(200);
        //添加重复元素
        set.add(100);
        set.add(300);
        set.add(400);
        set.add(200);

        //遍历集合
        for (Integer integer : set) {
            System.out.println(integer);
        }
    }
}

在这里插入图片描述
由运行结果可验证,LinkedHashSet集合输出的集合元素不会重复,且按照存储顺序输出

TreeSet

  1. 元素唯一且有序
package org.org.westos.demo;

import java.util.TreeSet;

public class MyClass {
    public static void main(String[] args) {
        TreeSet<Integer> set = new TreeSet<>();
        set.add(11);
        set.add(55);
        set.add(33);
        set.add(44);
        set.add(22);
        //添加重复元素
        set.add(11);
        set.add(55);
        for (Integer integer : set) {
            System.out.println(integer);
        }
    }
}

在这里插入图片描述
就目前元素唯一的特点,跟LinkedHashSet是一样的,但除此之外,TreeSet集合还有自己的特点,那就是可以对集合中的元素进行排序,这里已经对其采用了自然排序的方式

  1. 排序
    如果实现按从小到大或者从大到小的顺序输出
    根据方法返回值的正、负和0来决定此元素在红黑树中放置的左右顺序
    如果是正,作在右子树,如果是负,作为左子树,如果是0就不往里放
    然后在遍历集合时,以左中右的方式获取元素,这样,遍历出来的元素就是排好序的
    在这里插入图片描述
    (1)自然排序
    如果使用空参构造,就采用自然排序
    采用自然排序,就要求元素必须实现Comparable接口,并重写其中的compareTo方法
package org.org.westos.demo;

public class Student implements Comparable<Student>{
    //比较方法
    @Override
    public int compareTo(Student student){
        //根据年龄大小排序
        int num = this.age-student.age;
        //年龄一样不能说明是同一个对象,还得比较姓名
        //如果不比较,集合会当作是同一个元素,根据唯一性就不会放入
        int num2 = num==0?this.name.compareTo(student.name):num;
        //返回比较结果,只看正、负、0
        return num2;
    }
}

package org.org.westos.demo;

import java.util.TreeSet;

public class MyClass {
    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<>();
        treeSet.add(new Student("张三",33));
        treeSet.add(new Student("李四",22));
        treeSet.add(new Student("王五",11));
        treeSet.add(new Student("赵六",55));
        treeSet.add(new Student("田七",22));

        //遍历集合
        for (Student student : treeSet) {
            System.out.println(student);
        }
    }
}

在这里插入图片描述
这就是自然排序,这里Student类里省略了学生姓名、年龄和重写toString方法,只说重点
(2)比较器排序
如果使用有参构造,就采用比较器排序
采用比较器排序,需要传入一个比较器Comparator(接口)实现该接口中的compareTo方法,一般采用匿名内部类传入,就不需要重新编写一个比较器实现接口了

package org.org.westos.demo;

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

public class MyClass {
    public static void main(String[] args) {
        //使用匿名内部类传入比较器的子类对象
        TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //这里比较姓名长度来排序
                int num = o1.getName().length()-o2.getName().length();
                //姓名长度一样,还要比较姓名内容是不是一样
                int num2 = num==0?o1.getName().compareTo(o2.getName()):num;
                //姓名内容也一样,就按照年龄排序
                int num3 = num2==0?o1.getAge()-o2.getAge():num2;
                return num3;
            }
        });
        treeSet.add(new Student("张三gasrgasg",33));
        treeSet.add(new Student("李四afgargs",22));
        treeSet.add(new Student("王五gsrgasgsgd",11));
        treeSet.add(new Student("赵六asgsa",55));
        treeSet.add(new Student("田七gwrgarg",25));

        //遍历集合
        for (Student student : treeSet) {
            System.out.println(student);
        }
    }
}

在这里插入图片描述
在实现排序的时候,按什么排序,主要看方法里的逻辑语句
比如这里举的例子都是按从小到大排序,如果要重大到小,只需给返回值前加一个“-”号

个人感受:随着接触的集合越来越多,很容易混乱,要完全清楚的认识每个集合之间的联系与区别,就是多使用它们,熟悉它们

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值