Set
概述:
他是单列集合无序集合的顶层接口,继承了Collection的所有的共性功能以及遍历方式,没有自己独有的方法,所以不需要学习功能
特点:
1、无序
2、无索引
3、元素不可重复
使用场景:
用来对数据进行去重
使用Set集合就需要学习他的实现类,有一个典型的实现类 HashSet,HashSet集合为了实现Set集合的功能而出现的。
Set集合的遍历
一、数组法
1、toArray():
把集合变成Object数组 遍历数组获取元素【集合的元素类型会自动向上转型 需要向下转型使用】
2、toArray(T[ ] t):
把集合变成指定的类型的数组,再进行遍历
注意:
1、传入的指定的数组的长度正好和集合的长度一致,就把集合的数据存入传入的数组中
2、传入的指定的数组的长度小于集合的长度,集合的数据放不进传入的数组,根据传入数组的数据类型和集合的长度作为依据重新创建一个数组存放集合的数据
3、传入的指定的数组的长度大于集合的长度,不需要创建新数组集合的数据存入传入的数组中,后面多余的位置使用null 补充
代码示例
import java.util.HashSet;
public class setDemo {
public static void main(String[] args) {
// 使用Set集合
HashSet<Integer> set = new HashSet<Integer>();
// 添加数据到集合
set.add(10);
set.add(20);
set.add(30);
set.add(40);
set.add(50);
set.add(40);
set.add(30);
System.out.println(set); //去除了重复的内容
//数组遍历法
//转换为Object类型数组
Object[] array = set.toArray();
for (int i = 0; i < array.length; i++) {
//Integer it = array[i]; //无法存放,数据类型为Object类型
System.out.print(array[i] + " ");
}
System.out.println();
//数组法二
Integer[] arr1 = new Integer[set.size()]; //数组长度为集合长度 arr1与arr2中内容一样
//Integer[] arr1 = new Integer[2]; //会创建根据集合数据类型和长度重新创建一个数组 arr1无内容,会新创建一个arr2
//Integer[] arr1 = new Integer[10]; //后边多余位置用null填补 arr1 arr2 后边多于位置都为null
//把集合变成指定的类型的数组,再进行遍历
Integer[] arr2 = set.toArray(arr1);
for (int i = 0; i < arr2.length; i++) {
Integer it = arr2[i]; // 数据类型还是原来的类型
System.out.print(it + " ");
}
}
}
二、迭代器法
和Collection的迭代器遍历是一模一样的
步骤:
1、获取迭代器对象
2、while循环调用 hasNext 和 next方法遍历
代码示例:
import java.util.HashSet;
import java.util.Iterator;
public class setDemo {
public static void main(String[] args) {
// 使用Set集合
HashSet<Integer> set = new HashSet<Integer>();
// 添加数据到集合
set.add(10);
set.add(20);
set.add(30);
set.add(40);
set.add(50);
set.add(40);
set.add(30);
//迭代器法
//创建迭代器对象
Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
}
}
三、增强for
概述:
是一种固定格式的遍历方式,可以遍历所有容器【数组和集合】
底层其实还是迭代器遍历,使用的时候不能使用集合对象进行增删操作,迭代器对象我们不知道, 所以一般增强for遍历不会对集合进行增删操作,主要就是查看数据和获取数据
格式:
for(数据类型 变量名 : 容器名) {
对数据的操作逻辑
}
格式解释:
数据类型:遍历的容器中存放数据的类型
变量名:存放每次遍历获取到的数据(每遍历一次都是一个新值)
容器名:要遍历的容器
代码示例
import java.util.HashSet;
import java.util.Iterator;
public class setDemo {
public static void main(String[] args) {
// 使用Set集合
HashSet<Integer> set = new HashSet<Integer>();
// 添加数据到集合
set.add(10);
set.add(20);
set.add(30);
set.add(40);
set.add(50);
set.add(40);
set.add(30);
// foreach 【增强for遍历】
for (Integer integer : set) {
System.out.print(integer + " ");
}
}
}
set练习
随机生成 10 个 20~40 之间的随机数,存储在合适的集合中,并且进行遍历
要求:随机数不能重复
分析:
10个随机数生成10次够吗?不一定够,也不知道什么时候够,随机数要往集合放,集合存放的随机数不能有重复,哪个集合适合?Set集合满足要求,所以判断set集合的长度够不够10,够说明随机数10不用生成
代码示例:
import java.util.HashSet;
public class SetText {
public static void main(String[] args) {
//创建集合对象
HashSet<Integer> set = new HashSet<Integer>();
// 在循环中生成随机数 【不知道具体的次数 while循环】
while (set.size() < 10) {
//生成随机数20-40
set.add((int)(Math.random()*21 + 20)); //因为生成的随机数为double类型,需转为int
}
//遍历集合
for (Integer integer : set) {
System.out.print(integer + " ");
}
}
}
HashSet 保证元素唯一性的原理
概述:
set集合存放jdk提供的类对象的时候可以保证存放的对象的属性值唯一
set集合存放的是自定义的类对象:
重写hashCode和equals方法:可以保证存放对象的属性值唯一
没有重写hashCode和equals方法:只能保证对象唯一
hashCode():他会根据不同的对象生成对应哈希值
生成规律:
1、不同类的对象尽量生成不一样的哈希值
【可以生成相同的哈希值】
2、同类的不同对象根据是否重写hashCode方法:
没重写:
不同的对象生成的哈希值不一样
重写:
不同对象的属性值不一样:生成的哈希值不一样
不同对象的属性值一样:生成的哈希值一样
3、同一个对象多次的调用hashCode方法生成的哈希值尽量一样
4、equals方法返回值为true的两个对象的哈希值一样
Set集合保证元素唯一的原理:【必须掌握】
调用hashCode方法获取存入对象的哈希值和集合中已经拥有的对象的哈希值进行比较
不一致:要存放的是全新的对象直接存入集合中
一致:不能保证对象是否为唯一的对象
进一步调用equals方法比较哈希值一样的对象的属性值
不一样:说明是全新的对象 存入集合
一样:说明集合中已经存入该对象了,舍弃存入