1.Set集合概述及特点:
Set继承于Collection接口,是一个不允许出现重复元素,并且无序的集合,主要有HashSet、TreeSet、LinkedHashset等实现类。
2.Set 常用方法
package Demo;
import java.util.Collection;
import java.util.Iterator;
/**
* @Author: King
* @Description:人类的伟大是勇气的伟大,人类的赞歌是勇气的赞歌
* @Creat: 2021-11-25-14:37
*/
public class Test {
public interface Set<E> extends Collection<E> {
//添加功能
boolean add(E e);//如果Set中未包含此元素,则添加此元素
boolean addAll(Collection<? extends E> c);//如果 et 中没有指定collection中的所有元素,则将其添加到此set中
//删除功能
boolean remove(Object o);// 如果Set中包含指定元素,则将其移除
boolean removeAll(Collection<?> c);//移除Set中与指定collection重复的元素
void clear();// 移除此 set 中的所有元素
//长度功能
int size();//返回Set中的元素数
//判断功能
boolean isEmpty();//判断Set是否为空(包含元素),如果Set不包含元素,返回true
boolean contains(Object o);//如果Set中包含指定元素,则返回true
boolean containsAll(Collection<?> c);//如果此 set 包含指定collection的所有元素,则返回true。
boolean retainAll(Collection<?> c);//仅保留Set中与指定collection重复的元素
//获取Set集合的迭代器:
Iterator<E> iterator();
//把集合转换成数组
Object[] toArray();//返回一个包含Set中所有元素的数组
<T> T[] toArray(T[] a);//返回一个包含此 set 中所有元素的数组;返回数组的运行时类型是指定数组的类型。
}
}
3.HsahSet
a:HashSet的特点: 不允许出现重复因素; 允许插入Null值; 元素无序(添加顺序和遍历顺序不一致); 线程不安全,若2个线程同时操作HashSet,必须通过代码实现同步 b:HashSet如何保证元素的唯一性 当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。 HashSet 集合判断两个元素相等的标准: 两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。 结论:HashSet 保证元素唯一性是靠元素重写hashCode()和equals()方法来保证的,如果不重写则无法保证。
3.1 HashSet保证元素唯一性图解
3.2 HashSet保证元素唯一性
package Demo;
import java.util.HashSet;
import java.util.Iterator;
import java.util.function.Consumer;
/**
* @Author: King
* @Description:人类的伟大是勇气的伟大,人类的赞歌是勇气的赞歌
* @Creat: 2021-11-25-15:32
*/
public class MyTest {
public static void main(String[] args) {
//创建HashSet集合
HashSet<Student> hashSet = new HashSet<>();
System.out.println("HashSet集合初始长度"+hashSet.size());
//添加元素
hashSet.add(new Student("张三", 17));
hashSet.add(new Student("张三", 18));
hashSet.add(new Student("张三", 17));
hashSet.add(new Student("李四", 21));
hashSet.add(new Student("王五", 19));
hashSet.add(new Student("赵六", 18));
//遍历集合元素
//增强for循环
for (Object a : hashSet) {
System.out.println(a);
}
System.out.println("===================================================");
//迭代器遍历+0
Iterator<Student> iterator = hashSet.iterator();
while (iterator.hasNext()){
Student str=iterator.next();
System.out.println(str);
}
System.out.println("======================================================");
//forEach方法
hashSet.forEach(new Consumer<Student>() {
@Override
public void accept(Student student) {
System.out.println(student);
}
});
}
}
未重写hashCode()和equals()方法时,元素并未唯一,运行结果如下:
Student{name='张三', age=17}
Student{name='王五', age=19}
Student{name='张三', age=18}
Student{name='张三', age=17}
Student{name='李四', age=21}
Student{name='赵六', age=18}
储存的对象需要重写hashCode()和equals()方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
运行结果如下:
Student{name='王五', age=19}
Student{name='张三', age=18}
Student{name='张三', age=17}
Student{name='李四', age=21}
Student{name='赵六', age=18}
4 LinkedHashSet
数据结构:由链表和哈希表组成 •链表保证有序 哈希表保证元素唯一 •LinkedHashSet: 元素有序(存取顺序一致) , 并且唯一
4.1 LinkedHash 案例演示
package Demo;
import java.util.LinkedHashSet;
/**
* @Author: King
* @Description:人类的伟大是勇气的伟大,人类的赞歌是勇气的赞歌
* @Creat: 2021-11-28-16:13
*/
public class MyTest1 {
public static void main(String[] args) {
LinkedHashSet<Integer> set = new LinkedHashSet<>();
set.add(1);
set.add(1);
set.add(1);
set.add(20);
set.add(3);
set.add(9);
set.add(10);
set.add(12);
for (Integer s : set) {
System.out.print(s+"\t");
}
}
}
运行结果:
1 20 3 9 10 12
5 TreeSet
TreeSet: 底层数据结构是二叉数,元素唯一,且能对元素进行排序 排序: 自然排序 比较器排序 到底使用的是哪一种的排序取决于,构造方法. 注意:使用TreeSet集合进行元素的自然排序,那么对元素有要求,要求这个元素 必须实现Comparable接口 否则无法进行自然排序 保证元素的唯一性是靠compareTo方法的返回值来确定如果返回0 表示两个元素相等则不重复存储
5.1 TreeSet保证元素唯一和自然排序的原理和图解
5.2 二叉树存储数据保证唯一性的图
二叉树的数据结构 先存入一个树根 分两个叉 存储元素时 跟树根比较 小的放在左边 大的放在右边 如果相等就不存储 取的时候按照 左中右的顺序来取
5.3 自然排序案例演示
注意自然排序 此对象 必须实现Comparable接口 否则报错
TreeSet存储自定义对象并遍历练习
package Demo;
import java.util.TreeSet;
/**
* @Author: King
* @Description:人类的伟大是勇气的伟大,人类的赞歌是勇气的赞歌
* @Creat: 2021-11-28-16:38
*/
public class MyTest2 {
public static void main(String[] args) {
TreeSet<Student1> s1 = new TreeSet<>();
s1.add(new Student1("张三", 18));
s1.add(new Student1("张三", 18));
s1.add(new Student1("张三", 17));
s1.add(new Student1("李四", 18));
s1.add(new Student1("王五", 19));
s1.add(new Student1("赵六", 21));
for (Student1 student1 : s1) {
System.out.println(student1);
}
}
}
自定义Student1类,实现Comparable接口并重写compareTo方法
package Demo;
/**
* @Author: King
* @Description:人类的伟大是勇气的伟大,人类的赞歌是勇气的赞歌
* @Creat: 2021-11-28-16:49
*/
public class Student1 implements Comparable<Student1> {
private String name;
private int age;
public Student1(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student1 s) {
//按年龄大小排序
int num=this.age-s.age;
//年龄相同,还得比较姓名是否相同
int num1=num==0?this.name.compareTo(s.name):num;
return num1;
}
}
5.4 比较器排序案例演示
package Demo;
import java.util.Comparator;
import java.util.TreeSet;
/**
* @Author: King
* @Description:人类的伟大是勇气的伟大,人类的赞歌是勇气的赞歌
* @Creat: 2021-11-28-17:07
*/
public class MyTest3 {
public static void main(String[] args) {
TreeSet<Student> treeSet= new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student a, Student b) {
int num=a.getAge()-b.getAge();
int num1=num==0?a.getName().compareTo(b.getName()):num;
return num1;
}
});
treeSet.add(new Student("张三", 18));
treeSet.add(new Student("张三", 18));
treeSet.add(new Student("张三", 17));
treeSet.add(new Student("李四", 18));
treeSet.add(new Student("王五", 19));
treeSet.add(new Student("赵六", 21));
for (Student student : treeSet) {
System.out.println(student);
}
}
}
6 练习
案例1:
案例演示 需求:编写一个程序,获取10个1至20的随机数,要求随机数不能重复, 并把最终的随机数输出到控制台。 分析: a: 定义一个集合( 选HashSet 可以不重复;选TreeSet 不重复还可以排序) b: 产生随机数,把随机数添加到集合中 c: 判断集合的长度,使用while循环实现
package Demo;
import java.util.Random;
import java.util.TreeSet;
import java.util.function.Consumer;
/**
* @Author: King
* @Description:人类的伟大是勇气的伟大,人类的赞歌是勇气的赞歌
* @Creat: 2021-11-28-17:17
*/
public class MyTest4 {
public static void main(String[] args) {
Random random = new Random();
TreeSet<Integer> integers = new TreeSet<>();
while (integers.size()<10){
integers.add(random.nextInt(20)+1);
}
integers.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.print(integer+"\t");
}
});
}
}
案例2:
A:案例演示: 需求:键盘录入3个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台。 /** * 步骤: * a: 自定义一个学生类 * b: 创建一个TreeSet集合对象(使用比较器进行排序) * c: 键盘录入学生的数据,然后把学生的数据封装成一个学生对象,把学生对象添加到集合中 * d: 遍历集合 */
TreeSet存储自定义对象并遍历
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
/**
* @Author: King
* @Description:人类的伟大是勇气的伟大,人类的赞歌是勇气的赞歌
* @Creat: 2021-11-23-15:11
*/
public class Test5 {
public static void main(String[] args) {
TreeSet<Student1> s1 = new TreeSet<>(new Comparator<Student1>() {
@Override
public int compare(Student1 a, Student1 b) {
int num=a.Sum()-b.Sum();
int num1=num==0?a.getName().compareTo(b.getName()):num;
return num1;
}
});
for (int i = 1; i < 4; i++) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入第" + i + "个学生姓名");
String name = sc.nextLine();
Scanner sc1 = new Scanner(System.in);
System.out.println("请输入"+name + "的语文成绩" );
int chinese = sc.nextInt();
Scanner sc2 = new Scanner(System.in);
System.out.println("请输入" + name + "的数学成绩");
int math = sc.nextInt();
Scanner sc3 = new Scanner(System.in);
System.out.println("请输入" + name + "的英语成绩");
int english = sc.nextInt();
s1.add(new Student1(name,chinese,math,english));
}
System.out.print("排名\t"+"姓名\t" + "语文\t" + "数学\t" + "英语\t" + "总分");
System.out.println();
for (Student1 student : s1) {
System.out.println(student);
}
}
}
定义一个Student1类
/**
* @Author: King
* @Description:人类的伟大是勇气的伟大,人类的赞歌是勇气的赞歌
* @Creat: 2021-11-23-15:16
*/
public class Student1 {
private String name;//姓名
private int chinese;//语文成绩
private int math;//数学成绩
private int english;//英语成绩
private static int rank=1;//排名
public Student1() {
}
public Student1(String name, int chinese,int math,int english) {
this.name=name;
this.chinese=chinese;
this.math=math;
this.english=english;
}
//总分
public int Sum(){
return math+chinese+english;
}
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
@Override
public String toString() {
return rank+++"\t"+name+"\t"+chinese+"\t"+math+"\t"+english +"\t"+Sum();
}
}