Set系列集合特点
- 无序:存取顺序不一致
- 不重复:可以去除重复
- 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素
Set系列集合的实现类
- HashSet : 无序、不重复、无索引
- LinkedHashSet : 有序、不重复、无索引
- TreeSet : 可排序、不重复、无索引
Set接口中的方法上基本上与Collection的API一致。
HashSet :无序、不重复、无索引
哈希值: 对象的整数表现形式
- 如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
- 如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
- 但是在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞)
public class HashSetDemo {
public static void main(String[] args) {
HashStudent hashStudent = new HashStudent("zs", 12);
HashStudent hashStudent1 = new HashStudent("zs", 12);
//1.如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
// 2.如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
System.out.println(hashStudent.hashCode());//121780
System.out.println(hashStudent1.hashCode());//121780
//但是在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞)
System.out.println("abc".hashCode());//96354
System.out.println("acD".hashCode());//96354
}
}
案例:
需求:创建一个存储学生对象的集合,存储多个学生对象。使用程序实现在控制台遍历该集合。
要求:学生对象的成员变量值相同,我们就认为是同一个对象
package jihe;
import java.util.Objects;
public class HashSetDemo01_Student {
private String name;
private Integer age;
public HashSetDemo01_Student() {
}
public HashSetDemo01_Student(String name, Integer age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public Integer getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(Integer age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
HashSetDemo01_Student that = (HashSetDemo01_Student) o;
return Objects.equals(name, that.name) && Objects.equals(age, that.age);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public String toString() {
return "HashSetDemo01_Student{name = " + name + ", age = " + age + "}";
}
}
import java.util.HashSet;
public class HashSetDemo01 {
public static void main(String[] args) {
//创建学生对象
HashSetDemo01_Student s1 = new HashSetDemo01_Student("张三", 25);
HashSetDemo01_Student s2 = new HashSetDemo01_Student("李四", 25);
HashSetDemo01_Student s3 = new HashSetDemo01_Student("王五", 25);
HashSetDemo01_Student s4 = new HashSetDemo01_Student("王五", 25);
//创建集合用来添加数据
HashSet<HashSetDemo01_Student> hs = new HashSet<>();
//添加集合元素
System.out.println(hs.add(s1));//true
System.out.println(hs.add(s2));//true
System.out.println(hs.add(s3));//true
System.out.println(hs.add(s4));//false
System.out.println(hs);
}
}
运行结果:
LinkedHashSet : 有序、不重复、无索引
student和上面HashSet的student一样不重复贴代码
public class LinkedHashSetDemo {
public static void main(String[] args) {
//创建学生对象
HashSetDemo01_Student s1 = new HashSetDemo01_Student("张三", 25);
HashSetDemo01_Student s2 = new HashSetDemo01_Student("李四", 25);
HashSetDemo01_Student s3 = new HashSetDemo01_Student("王五", 25);
HashSetDemo01_Student s4 = new HashSetDemo01_Student("王五", 25);
LinkedHashSet<HashSetDemo01_Student> lh = new LinkedHashSet<>();
System.out.println(lh.add(s1));//true
System.out.println(lh.add(s2));//true
System.out.println(lh.add(s3));//true
System.out.println(lh.add(s4));//false
System.out.println(lh);
}
TreeSet : 可排序、不重复、无索引
mport java.util.Iterator;
import java.util.TreeSet;
/**
* 利用TreeSet存储数据并进行排序
* */
public class TreeSetDemo {
public static void main(String[] args) {
//创建集合对象
TreeSet<Integer> ts= new TreeSet<>();
//添加元素
ts.add(4);
ts.add(1);
ts.add(2);
ts.add(5);
ts.add(3);
ts.add(3);
//打印集合
System.out.println(ts);//[1, 2, 3, 4, 5]
System.out.println("---------------------迭代器----------------------");
//遍历集合
//迭代器
Iterator<Integer> iterator = ts.iterator();
while (iterator.hasNext()){
Integer next = iterator.next();
System.out.println(next);
}
System.out.println("----------------------增强for---------------------");
//增强for
for (Integer t : ts) {
System.out.println(t);
}
}
}
输出结果:
TreeSet默认的比较规则:
- 对于数值类型: Integer ,Double,默认按照从小到大的顺序进行排序。
- 对于字符、字符串类型:按照字符在ASCII码表中的数字升序进行排序。
方式一:案例:利用TreeSet方法比较要求按照学生的年龄进行排序, 同年龄按照姓名字母排列(暂不考虑中文同姓名),同年龄认为是同一个人。
public class TreeSetDemo2_Student implements Comparable<TreeSetDemo2_Student>{
private String name;
private Integer age;
public TreeSetDemo2_Student() {
}
public TreeSetDemo2_Student(String name, Integer age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public Integer getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(Integer age) {
this.age = age;
}
public String toString() {
return "TreeSetDemo2_Student{name = " + name + ", age = " + age + "}";
}
@Override
public int compareTo(TreeSetDemo2_Student o) {
//排序规则Age
//返回值:
//负数:表示当前要添加的元素是小的,存在左边
//正数:表示当前要添加的元素是大的,存在右边
//0:表示当前要添加的元素已经存在 ,舍弃
return this.getAge()-o.getAge();
}
}
import java.util.TreeSet;
public class TreeSetDemo2 {
public static void main(String[] args) {
//创建三个学生对象
TreeSetDemo2_Student s1 = new TreeSetDemo2_Student("zhangsan", 25);
TreeSetDemo2_Student s2 = new TreeSetDemo2_Student("lisi",23 );
TreeSetDemo2_Student s3 = new TreeSetDemo2_Student("wangwu", 22);
//创建集合
TreeSet<TreeSetDemo2_Student> ts = new TreeSet<>();
//添加元素
ts.add(s1);
ts.add(s2);
ts.add(s3);
//打印元素
System.out.println(ts);
}
}
输出结果:
方式二:案例:要求:存入四个字符串“c”,“ab”,“df”,"qwer" 按照长度排序,如果一样长则按照首字母排序。
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetDemo3 {
public static void main(String[] args) {
//创建集合
//o1:表示当前要添加的元素
//o2:表示当前存在的元素
//返回值规则和方式一一样
TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int i = o1.length() - o2.length();
i = i == 0 ? o1.compareTo(o2) : i;
return i;
}
});
//添加元素
ts.add("c");
ts.add("ab");
ts.add("df");
ts.add("qwer");
//打印集合
System.out.println(ts);
}
}
输出结果: