Javase之集合体系(3)之Set及其子类知识

集合体系之Set及其子类知识

Set(接口)

public interface Set<E>extends Collection<E>

​ 特点:无序(存储顺序与取出顺序不一致,但它有内在的存储顺序该顺序通过哈希表生成,有时在输入时可能与其内在顺序相同,但之并不代表其有序,多输入几个数据就会发现其无序性),唯一。

其方法与Collection相同,是Set集合框架的顶层接口,不做过多讲解。

HashSet(类)

public class HashSet<E>extends AbstractSet<E>
implements Set<E>, Cloneable, Serializable

HashSet实现唯一性的原理:

​ 底层代码中虽然较为复杂,但是还是可以看出其依赖了hashCode()与equals()方法;

步骤:

​1. 首先比较哈希值
(1)如果相同,继续走,比较的值值或equals()方法

​(2) 如果不同,添加到集合中

按照方法的步骤来说:

​ 1.先观察由hashCode()实现的hash()方法值是否相同

​ (1)相同:走equals()方法;

​ <1>返回true:说明元素重复,没有添加到集合中;

​ <2>返回false:说明元素不重复,以添加到集合中

​ (2)不同:就添加元素到集合

如果类没有重写这两个方法,默认使用Object。一般来说不相同;

  • HashSet的底层数据类型为哈希表(元素是链表的数组)由HsahMap实现,哈希表依赖于哈希值存储,

LinkedHashSet(类)

public class LinkedHashSet<E>extends HashSet<E>
implements Set<E>, Cloneable, Serializable

特点:底层由链表和哈希表实现,

通过链表保证元素有序性,通过哈希表实现元素唯一性。

  • 其无特殊方法,使用去父类方法操作即可

TreeSet(类)

public class TreeSet<E>extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, Serializable

特点:能够按照某种规则对元素排序

排序有两种方式:

1.自然排序

​ TreeSet默认自然排序

​ 如果一个自定义对象要实现自然排序,就必须实现Comparable接口

2.比较器排序

​ 在声明对象时使用带参构造选择构造器,用匿名内部类实现比较器

如果自然排序和比较器排序同时存在优先使用比较器排序

TreeSet集合保证元素排序和唯一性的原理:

唯一性:根据返回值是否为0来决定。

排序:

​ 1.自然排序(元素具备比较性)

​ 让元素所属的类实现自然排序接口Comparable

​ 2.比较器排序(集合具备比较性)

​ 让集合的构造方法接收一个比较器的子类对象Comparator

两种排序实例:

  • 自然排序
import java.util.TreeSet;

//通过泛型来约束Compareable的比较类型
class Student implements Comparable<Student>{
    private int age;
    private String name;

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

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

    @Override
    public int compareTo(Student s) {
        //此处只是判断了年龄的条件,但是除了年龄外还有姓名不相同
        // 但年龄相同的元素被去掉了,所以还要判断年龄是否相同
        //而在此处需要判断所有元素是否相同,比较时基本元素直接比较,
        //比较引用类型时比较它们基本类型
//        return this.age - s.age;
        int mun = this.age - s.age;
        return mun == 0?this.name.compareTo(s.name):mun;
    }
}

public class treeset的自然排序 {
    public static void main(String[] args) {
        Student s1 = new Student("aa",34);
        Student s2 = new Student("bb",24);
        Student s3 = new Student("cc",32);
        Student s4 = new Student("dd",36);
        Student s5 = new Student("ee",36);
        TreeSet<Student> h = new TreeSet<>();
        h.add(s1);
        h.add(s2);
        h.add(s3);
        h.add(s4);
        h.add(s5);
        System.out.println(h);
    }
}

  • 比较器排序
import java.util.Comparator;
import java.util.TreeSet;

class Person {
    private int age;
    private String name;

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

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

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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


public class tree的比较器排序 {
    public static void main(String[] args) {

        TreeSet<Person> ts = new TreeSet<>(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                int num = o1.getAge() - o2.getAge();
                return num == 0?o1.getName().compareTo(o2.getName()):num;
            }
        });

        Person p1 = new Person("aa",2);
        Person p2 = new Person("bb",3);
        Person p3 = new Person("cc",4);
        Person p4 = new Person("dd",1);
        Person p5 = new Person("ee",2);
        Person p6 = new Person("aa",2);

        ts.add(p1);
        ts.add(p2);
        ts.add(p3);
        ts.add(p4);
        ts.add(p5);
        ts.add(p6);

        for (Person p:ts){
            System.out.println(p.getName()+"====="+p.getAge());
        }
    }
}

两种排序自然排序适合多次进行排序时使用,而比较器排序适合排序次数不多的情况。而且如果先实现了自然排序,再修改了类的属性则重写的自然排序也要进行修改。但是比较器排序没有这样的问题,因为其在使用时才会被重写。

posted @ 2019-03-04 10:26  紫月冰凌  阅读(211)  评论(0编辑  收藏  举报