0
点赞
收藏
分享

微信扫一扫

Set接口(笔记)

非常帅气的昵称吧 2022-03-23 阅读 31
java学习

1.Set接口的介绍(记住)

java.util.Set<E>接口 extends Collection<E>接口
Set接口的特点:
1.不允许存储重复的元素 add(1)  add(1)==>集合中只有一个1
2.不包含带索引的方法,里边的方法和Collection接口一模一样

2.HashSet集合的介绍和基本使用(重点)
在这里插入图片描述

package com.itheima.demo04Set;

import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;

/*
    java.util.HashSet<E> implements Set<E>接口
    HashSet集合的特点:
        此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。
        它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。
   1.不允许存储重复的元素
   2.不包含带索引的方法(get,set,remove)==>不能使用普通for循环遍历
   3.是一个无序的集合:存储的元素和取出的元素[有可能]不一致
   4.底层是一个哈希表结构
        JDK1.8版本之前:数组+单向链表
        JDK1.8版本之后:数组+单向链表|数组+红黑树
 */
public class Demo01HashSet {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("aaa");
        set.add("bbb");
        set.add("aaa");
        set.add("ccc");
        set.add("ddd");
        System.out.println(set);//[aaa, ccc, bbb, ddd]

        HashSet<Integer> set2 = new HashSet<>();
        Collections.addAll(set2,1,2,3,4,5);
        System.out.println(set2);//[1, 2, 3, 4, 5]

        //使用迭代器遍历Set集合
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }
        System.out.println("------------------------");
        //使用增强for循环遍历Set集合
        for (String s : set) {
            System.out.println(s);
        }
    }
}

3.哈希值(扩展知识点)
在这里插入图片描述

package com.itheima.demo04Set;

/*
    哈希值(扩展知识点_了解)
    Obejct类有一个方法:
        int hashCode() 返回该对象的哈希码值。
    哈希值:就是一个十进制的整数,由操作系统返回
    hashCode方法底层源码:
        public native int hashCode();
        native:本地方法,调用不是java语言写的方法,调用操作系统(其他语言)底层的方法
    toString方法源码:对象的地址值
        public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
        Integer.toHexString(hashCode()):把十进制(0-9)的整数,转换为十六进制(0-9,a-f)
    ----------------------------------------------------------------------------------
    hashCode返回的对象的地址值,是一个假的虚拟的地址(看着玩),不是对象实际在内存中地址
 */
public class Demo02HashCode{
    public static void main(String[] args) {
        Person p1 = new Person();
        int h1 = p1.hashCode();
        System.out.println(h1);//1163157884==>1
        System.out.println(p1.toString());//com.itheima.demo04Set.Person@4554617c==>1

        Person p2 = new Person();
        System.out.println(p2.hashCode());//1956725890==>1
        System.out.println(p2.toString());//com.itheima.demo04Set.Person@74a14482==>1
        System.out.println(p1==p2);//比较的两个对象的实际地址 false
    }
}
package com.itheima.demo04Set;

public class Person extends Object{
    //重写Object类的hashCode方法
    @Override
    public int hashCode() {
        return 1;
    }
}

4.String类的哈希值(扩展知识点)

在这里插入图片描述

package com.itheima.demo04Set;

/*
    String类的哈希值(扩展知识点_了解)
    String类重写了Object类的hashCode方法
    规则:
        相同的字符串,返回的哈希值是一样的
        不同的字符串,返回的哈希值也有可能一样
 */
public class Demo03StringHashCode {
    public static void main(String[] args) {
        String s1 = new String("abc");
        String s2 = new String("abc");
        System.out.println(s1.hashCode());//96354
        System.out.println(s2.hashCode());//96354

        System.out.println("重地".hashCode());//1179395
        System.out.println("通话".hashCode());//1179395
        System.out.println('a'+0);//97
        System.out.println('重'+0);//37325
    }
}

在这里插入图片描述
5.HashSet集合存储数据的结构(哈希表)
在这里插入图片描述
6.使用HashSet集合存储String不重复的原理(扩展知识点)

package com.itheima.demo04Set;

import java.util.HashSet;

/*
    使用HashSet集合存储String不重复的原理(扩展知识点_了解)
    String类(Integer,Double...)重写了Object类的hashCode方法和equals方法,用于判断元素是否重复
 */
public class Demo04HashSetSaveString {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        String s1 = new String("abc");
        String s2 = new String("abc");
        set.add(s1);
        set.add(s2);
        set.add("重地");
        set.add("通话");
        set.add("abc");
        System.out.println(set);
    }
}

在这里插入图片描述
7.HashSet存储自定义类型元素(重点中的重点)

同名同年龄的Student对象,视为重复的元素,只能存储一个
Student类重写hashCode方法和equals方法,来保证元素不重复

快捷键:alt+insert==>选择 equals() and hashCode()

package com.itheima.demo04Set;

import java.util.HashSet;

/*
    HashSet存储自定义类型元素(重点中的重点)
    自定义类型:Student,Person,Animal...
    要求:同名同年龄的学生只能存储一次(不重复)
    解决:
        自定义类型重写hashCode方法和equals方法保证元素唯一
 */
public class Demo05HashSetStudent {
    public static void main(String[] args) {
        HashSet<Student> set = new HashSet<>();
        Student s1 = new Student("a",10);
        Student s2 = new Student("a",10);
        System.out.println(s1.hashCode());//1163157884==>107
        System.out.println(s2.hashCode());//1956725890==>107
        set.add(s1);
        set.add(s2);
        Student s3 = new Student("b",9);
        set.add(s3);
        for (Student s : set) {
            System.out.println(s.getName()+"\t"+s.getAge());
        }
    }
}
package com.itheima.demo04Set;

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }

    /*
        重写Object类的hashCode方法:了解
            name.hashCode()+age;
        ---------------------------------------
        Student s1 = new Student("a",10);
        Student s2 = new Student("a",10);
        set.add(s1);计算s1的哈希值 97+10=107 在集合中找有没有107这个哈希值的元素,发现没有,直接把s1存储到集合中
        set.add(s2);计算s2的哈希值 97+10=107 在集合中找有没有107这个哈希值的元素,发现有,s2.equals(s1)==>true
            两个元素的哈希值相同,equals返回true,认定两个元素相同,不会把s2存储到Set集合中
        --------------------------------------------------------------------------------
        Student s3 = new Student("b",9);
        set.add(s3);计算s2的哈希值 98+9=107 在集合中找有没有107这个哈希值的元素,发现有,s3.equals(s1)==>false
             两个元素的哈希值相同,equals返回false,认定两个元素不同,会把s3存储到Set集合中
        --------------------------------------------------------------------------------
        降低不同元素出现相同哈希值的概率
             name.hashCode()*2+age;
             set.add(s1);计算s1的哈希值 97*2+10=204
             set.add(s3);计算s3的哈希值 98*2+9=205 发现集合中没有205这个哈希值的元素,直接存储到集合中
             name.hashCode()*31+age;
     */
    /*@Override
    public int hashCode() {
        return name.hashCode()+age;
    }*/
    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    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;
    }
}

8.LinkedHashSet集合(了解)
在这里插入图片描述

package com.itheima.demo04Set;

import java.util.HashSet;
import java.util.LinkedHashSet;

/*
    java.util.LinkedHashSet<E>集合extends HashSet<E>集合
        具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。
        此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。
    特点:
        1.不允许存储重复的元素
        2.不包含带索引的方法(get,set,remove)==>不能使用普通for循环遍历
        3.是一个有序的集合
        4.底层是哈希表+单向链表==>底层就组成双向链表结构
            JDK1.8版本之前:数组+单向链表+单向链表
            JDK1.8版本之后:数组+单向链表|数组+红黑树+单向链表
 */
public class Demo06LinkedHashSet {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("aaa");
        set.add("bbb");
        set.add("aaa");
        set.add("ccc");
        set.add("ddd");
        System.out.println(set);//[aaa, ccc, bbb, ddd] 不允许重复,无序集合

        LinkedHashSet<String> linked = new LinkedHashSet<>();
        linked.add("aaa");
        linked.add("bbb");
        linked.add("aaa");
        linked.add("ccc");
        linked.add("ddd");
        System.out.println(linked);//[aaa, bbb, ccc, ddd] 不允许重复,有序集合
    }
}
举报

相关推荐

0 条评论