一、概述
Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素,而且Set接口中元素无序。
本节需要了解的知识点:
什么是哈希表呢?
哈希表底层使用的也是数组机制,数组中存放对象,这些对象存放的位置比较特殊,当把这些对象存入数组中时,会根据这些对象的特有数据结合相应的算法(hashCode),计算出这个对象在数组中的位置,然后把这个对象存放在数组中。而这样的数组就称为哈希数组,即就是哈希表。
当向哈希表中存放元素时,会调用Object类中的hashCode方法。由于任何对象都是Object类的子类,所以任何对象有拥有这个方法。这里需要注意,如果两个对象hashCode方法算出结果一样,这样现象称为哈希冲突,这时会调用对象的equals方法,比较这两个对象是不是同一个对象,如果equals方法返回的是true,那么就不会把第二个对象存放在哈希表中,如果返回的是false,就会把这个值存放在哈希表中。
保证Set集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。
示例:set和list的比较
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class demo_set无序 {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("aaa");
list.add("ccc");
list.add("aaa");
list.add("bbb");
//不保存重复的元素且无序
Set set=new HashSet();
set.add("ccc");
set.add("aaa");
set.add("bbb");
set.add("aaa");
System.out.println(list);
System.out.println(set);
}
}
运行结果:
二、HashSet存储自定义对象
当使用HashSet存储自定义对象时,我们要重写hashCode()和equals()方法
因为:
当调用HashSet的add()方法,会先判断hashCode()是否相同,
如果相同,就会再判断equals(),如果equals()也相同,那么就不存。
比如班上有两个人姓名和年龄都相同,但是必须要把这两个人都存起来。
示例:
import java.util.HashSet;
public class demo_set添加对象 {
public static void main(String[] args) {
HashSet<Student> hashSet=new HashSet<>();
hashSet.add(new Student("yyy",21));
hashSet.add((new Student("wtc",21)));
//添加重复元素
hashSet.add((new Student("wtc",21)));
System.out.println(hashSet);
}
}
class Student{
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
return super.equals(o);
}
@Override
public int hashCode() {
return this.name.hashCode()+age;
}
@Override
public String toString() {
return "姓名:" + name +
" 年龄:" + age;
}
}
运行结果:
三、练习题
1.获取10个不重复的1-20之间的随机数
import java.util.HashSet;
import java.util.Random;
public class demo_获取10个不重复随机数 {
public static void main(String[] args) {
HashSet hashSet=new HashSet();
Random r=new Random();
while(hashSet.size()<10){
//范围1-20
int i=r.nextInt(20)+1;
hashSet.add(i);
}
System.out.println(hashSet);
}
}
运行结果:
四、TreeSet接口
特点:1.元素是有序的
2.不能存储重复的元素
存储自定义对象: 需要告诉它应该按照什么来排序
需要实现接口:Compareble
实现接口的抽象方法:compareTo
在它里面去编写排序的规则
compareTo里面可以返回三种值
* 1.大于0 * 2.小于0 * 3.等于0 *
示例:
import java.util.TreeSet;
public class demo_TreeSet {
public static void main(String[] args) {
TreeSet treeSet=new TreeSet();
treeSet.add("aaa");
treeSet.add("ddd");
treeSet.add("bbb");
treeSet.add("ccc");
treeSet.add("aaa");
System.out.println(treeSet);
TreeSet<Students> treeSet1=new TreeSet<>();
treeSet1.add(new Students("yyy",20));
treeSet1.add(new Students("wtc",23));
treeSet1.add(new Students("wt",22));
treeSet1.add(new Students("wtc",20));
System.out.println(treeSet1);
}
}
class Students implements Comparable<Students>{
String name;
int age;
public Students(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Students o) {
//解决年龄相同的问题,按年龄排序
int i=this.age-o.age;
return i==0?this.name.compareTo(o.name):i;
}
@Override
public String toString() {
return "Students{" +
"姓名:" + name +
" 年龄:" + age +
'}';
}
}
运行结果:
五、通过构造方法传入排序比较器
解决问题:不能在对象类内进行改动去实现接口
示例:
import java.util.Comparator;
import java.util.TreeSet;
public class demo_构造方法传入比较器 {
public static void main(String[] args) {
//第一种写法
Comparator comparator=new Comparator<Person>(){
@Override
public int compare(Person o1, Person o2) {
//实现按年龄排序
int i=o1.age-o2.age;
return i==0?o1.name.compareTo(o2.name):i;
}
};
TreeSet<Person> treeSet=new TreeSet<>(comparator);
/**第二种写法
* TreeSet<Person> treeSet=new TreeSet<>(ew Comparator<Person>(){
* @Override
* public int compare(Person o1, Person o2) {
* //实现按年龄排序
* int i=o1.age-o2.age;
* return i==0?o1.name.compareTo(o2.name):i;
* }
* });
*/
treeSet.add(new Person("YYY",18));
treeSet.add(new Person("wtc",21));
treeSet.add(new Person("wt1",21));
System.out.println(treeSet);
}
}
class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"姓名:" + name + '\'' +
" 年龄:" + age +
'}';
}
}
运行结果: