目录

1、Set接口简介

2、HashSet

简介

特点

3、哈希值

4、HashSet存储的数据结构

5、set集合存储元素不重复原理

基本思路:

6、HashSet存储自定义类型元素

1、概述

2、使用

person类:

Test测试类:

7、LinkedHashSet(了解)

简介:

8、可变参数

使用场景:

使用格式:

可变参数原理:

注意事项:


1、Set接口简介

一个不包含重复元素的集合;

此接口没有索引,没有带索引的方法; 

 

set接口跟Collection方法基本一致,主要研究其实现类;

 

2、HashSet

简介

此类实现set接口,由哈希表(实际上是一个HashMap实例)支持;

它不保证set的迭代顺序,特别是不保证该顺序恒久不变;

允许使用null元素;

此实现不是同步的(多线程,速度快);

 

特点

一个不包含重复元素的集合;

此接口没有索引,没有带索引的方法; 

无序的集合,存取元素的顺序可能不一致;

底层是一个HashMap结构(查询速度快);

        //多态方式实现HashSet
        Set<Integer> set = new HashSet<>();
        set.add(7);
        set.add(1);
        set.add(4);
        set.add(4);//不允许存储重复的数据,编译器智能提醒
        //迭代器遍历
        Iterator<Integer> integerIterator = set.iterator();
        while (integerIterator.hasNext()) {
            System.out.println(integerIterator.next());//1 4 7 重复是数据没存进来
        }
        //增强型for循环遍历,底层是迭代器
        for (int i : set){
            System.out.println(i);//1 4 7 重复是数据没存进来
        }

 

3、哈希值

哈希值是一个十进制的整数,由系统随机给出(就是对象的地址值,是第一个逻辑地址,是模拟出来的地址值,不是数据实际存储的的物理地址值)

获取哈希值的方法 int hashCode();

 

4、HashSet存储的数据结构

JDK1.8之前:哈希表 = 数组 + 链表;

JDK1.8之后:哈希表 = 数组 + 红黑树(提高查询速度);

哈希表的特点:查询速度快;

Java中Set集合_System

 

5、set集合存储元素不重复原理

基本思路:

当set调用add方法的时候,会将当前所要存储的元素的哈希值在集合中查找,若未查找到,则存储集合,若查找到则会调用equals方法,与集合中已经存在的相同哈希值的元素进行比较,若返回true则不再将所要存储的元素存储到集合中,若返回false则将所要存储的元素存储到集合中。

Java中Set集合_set_02

 

6、HashSet存储自定义类型元素

1、概述

要想将自定义的类存入到HashSet必须重写hashCode和equals方法(以保障元素唯一);

 

2、使用

要求:同名和同年龄的人视为一个人,不允许存储两个;

person类:

public class Person {
    private String name;
    private int age;

    public Person() {
    }

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

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

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

    @Override
    public int hashCode() {
        return Objects.hash(name, 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;
    }
}

Test测试类:

public class MyHashSet {
    public static void main(String[] args) {
        Set<Person> set = new HashSet<>();
        set.add(new Person("小明",18));
        set.add(new Person("小兰",19));
        set.add(new Person("小明",18));
        System.out.println(set);
        //[Person{name='小兰', age=19}, Person{name='小明', age=18}]
    }
}

 

7、LinkedHashSet(了解)

简介:

具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现;

此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表;

底层是哈希表+链表;

HashSet:无序的,不允许重复;

LinkedHashSet:有序的,不允许重复;

 

8、可变参数

使用场景:

当参数的数据类型已经确定,但参数的个数不确定,此时可使用可变参数;

使用格式:

修饰符 返回值类型 方法名(数据类型...变量名){}

可变参数原理:

可变参数底层是一个数组,根据传入的参数数量不同,创建不同长度的数组,来存储这些参数;

传递的参数数量可以为0;

public class Test {
    public static void main(String[] args) {
        System.out.println(sum(1,2,3,4,5,6,7,8,9,0,7,56,4,4,6,67,64));//253
    }
    public static int sum(int...arr){
        //实际上arr可以当做一个数组用
        int sum = 0;
        for(int i:arr){
            sum+=i;
        }
        return sum;
    }
}

注意事项:

只能有一个可变参数;

如果有多个参数,可变参数必须写在参数列表末尾;