一、 HashSet集合的介绍
java.util.Set
接口 extends Collection
接口
Set
接口的特点:
- 不允许重复的元素
- 没有索引,没有带索引的方法,也不能使用普通的for循环遍历
java.util.HashSet
集合implements Set
接口
HashSet特点:
- 不允许重复的元素
- 没有索引,没有带索引的方法,也不能使用普通的for循环遍历
- 是一个无序的集合,存储元素和取出元素的顺序有可能不一致
- 底层是一个哈希表结构(查询的速度非常的快)
import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * @author :CaiCai * @date : 2022/4/13 14:30 */ /* java.util.Set接口 extends Collection接口 Set接口的特点: 不允许重复的元素 没有索引,没有带索引的方法,也不能使用普通的for循环遍历 java.util.HashSet集合 implements Set接口 HashSet特点: 不允许重复的元素 没有索引,没有带索引的方法,也不能使用普通的for循环遍历 是一个无序的集合,存储元素和取出元素的顺序有可能不一致 底层是一个哈希表结构(查询的速度非常的快) */ public class demoSet { public static void main(String[] args) { Set<Integer> set =new HashSet<>(); // 使用add方法往集合中添加元素 set.add(1); set.add(2); set.add(3); set.add(1); //使用迭代器遍历Set集合 Iterator<Integer> it=set.iterator(); while(it.hasNext()){ Integer n=it.next(); System.out.println(n); } System.out.println("================"); //使用增强for循环遍历Set结合 for(Integer i: set){ System.out.println(i); } } }
二、哈希值
哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到的地址,不是数据实际存储的物理地址
在Object
类中有一个方法,可以获取对象的哈希值
int hashCode()
返回该对象的哈希码值
hashCode
的源码:代表该方法调用的是本地操作系统的方法
public native int hashCode()
; native
:代表该方法调用的是本地的操作对象
public class demo03 { public static void main(String[] args) { Person p1=new Person(); int h1=p1.hashCode(); System.out.println(h1);//23934342 Person p2=new Person(); int h2=p2.hashCode(); System.out.println(h2);//22307196 /* String类的哈希值 String类重写Object类的hashCode方法 */ 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 } }
三、HashSet集合存储数据的结构
哈希冲突:两个元素不同,但是哈希值相同
四、Set集合存储元素不重复的原理
五、HashSet存储自定义类型的元素
public class Person1 { private String name; private int age; public Person1() { } public Person1(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person1{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person1 person1 = (Person1) o; return age == person1.age && Objects.equals(name, person1.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; } }
/* HashSet存储自定义类型的元素 存储元素(String,Integer,……,Student,Person……)必须重写hashCode方法和equals方法 要求:同名和同年龄的人视为同一个人,只能存储一次 */ public class DemoHashPerson { public static void main(String[] args) { //创建HashSet集合存储Person HashSet<Person1> set=new HashSet<>(); Person1 p1=new Person1("张三",20); Person1 p2=new Person1("张三",20); Person1 p3=new Person1("王五",21); System.out.println(p1.hashCode());//24022540 System.out.println(p2.hashCode());//24022540 System.out.println(p1==p2);//false System.out.println(p1.equals(p2));//true set.add(p1); set.add(p2); set.add(p3); System.out.println(set); } }
六、LinkedHashSet集合
java.util.linkedHashSet
集合extends HashSet
集合
linkedHashSet
集合的特点:
底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序)保证元素有序
/* java.util.linkedHashSet集合extends HashSet集合 linkedHashSet 集合的特点: 底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序)保证元素有序 */ public class demoLinkHashSet { public static void main(String[] args) { HashSet<String> set=new HashSet<>(); set.add("www"); set.add("abc"); set.add("abc"); set.add("itcns"); System.out.println(set);//[itcns, abc, www]无序 不允许重复 LinkedHashSet<String> linked=new LinkedHashSet<>(); linked.add("www"); linked.add("abc"); linked.add("abc"); linked.add("yyy"); System.out.println(linked);//[www, abc, yyy] 有序 不允许重复 } }