1、HashSet:
1)、 Set集合的特点
-
元素存储可以有序,可以无序(要看选择的具体子类 HashSet 无序 LinkedHashSet(有序),TreeSet(排序))
-
没有索引,不能通过索引获取元素(即也不能使用普通for循环遍历)
-
不可以存储重复的元素
在某一些特定的场景,我们想要实现不能保存重复的元素的效果,此时使用Set集合就非常的合适
2)、 概述及特点
概述:HashSet集合是Set集合的子类,是一个具体的类。底层使用Hash表存储数据(hash本质就是一个数组)。HashSet存储数据使用的是HashMap的key部 分(HashMap我们明天会学习到,是一个双列的存储数据的结构)
存储数据的结构:数组 + 链表 + 红黑树
特点
-
元素存储无序
-
没有索引,不能通过索引获取元素(即也不能使用普通for循环遍历)
-
不可以存储重复的元素
3)、 常用方法
1>、增加:
import java.util.HashSet;
import java.util.Set;public class AddDemo {public static void main(String[] args) {Set<Integer> set = new HashSet<>();// 添加元素set.add(1);set.add(2);set.add(3);set.add(17);System.out.println(set);Set<String> set2 = new HashSet<>();// 添加元素set2.add("zhangsan");set2.add("lisi");set2.add("wangwu");set2.add("zhaoliu");set2.add(null);// 允许添加null值,但是只能添加一次System.out.println(set2);}
}
2>、删除:
import java.util.HashSet;
import java.util.Set;public class RemoveDemo {public static void main(String[] args) {Set<String> set = new HashSet<>();// 添加元素set.add("zhangsan");set.add("lisi");set.add("wangwu");set.add("zhaoliu");System.out.println(set);// 删除元素boolean flag = set.remove("zhangsan");System.out.println(flag);System.out.println(set);System.out.println("-----优雅的分隔符-----");// 删除部分元素Set<String> set2 = new HashSet<>();set2.add("lisi");set2.add("zhaoliu");set2.add("zhangsan");boolean result = set.removeAll(set2);System.out.println(result);System.out.println(set);// 清空集合set.removeAll(set);System.out.println(set);set.clear();System.out.println(set);}
}
3>、修改:
import java.util.HashSet;
import java.util.Set;public class UpdateDemo {public static void main(String[] args) {Set<String> set = new HashSet<>();// 添加元素set.add("zhangsan");set.add("lisi");set.add("wangwu");set.add("zhaoliu");System.out.println(set);// 没有修改的方法}
}
4>、查询:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;public class SelectDemo {public static void main(String[] args) {Set<String> set = new HashSet<>();// 添加元素set.add("zhangsan");set.add("lisi");set.add("wangwu");set.add("zhaoliu");System.out.println(set);// 获取集合的长度System.out.println(set.size());// 查询是否包含某一个指定的值boolean flag = set.contains("zhangsan");System.out.println(flag);// 集合是否为空System.out.println(set.isEmpty());// 增强for循环for(String str : set) {System.out.println(str);}System.out.println("----------------------");// 迭代器Iterator<String> iterator = set.iterator();while(iterator.hasNext()){String value = iterator.next();System.out.println(value);}}
}
4)、底层原理图:
备注:它的底层是用HashMap实现的, HashMap也是类似原理,后面章节会更具体的讲解HashMap。
2、TreeSet:
1)、学习了hashSet,无序不可重复。但是,有些时候,某些场景还是需要按照指定要求对数据进行排序。也就是说,要求我们的数据有序(此处 的有序指的不是存入顺序与取出顺序一致,而是按照指定的规则从大到小或者从小到大排序),比如,在录入学生考试成绩的时候 ,我就希望能够按照绩来进行排序。
很显然,这个功能使用HashSet没有办法实现,所以,我们需要学习TreeSet树结构,二叉树
2)、 概述及特点
概述:TreeSet实现了Set接口,存储的元素有序,可以按照一定的规则进行排序,具体排序方式取决于构造方法。
-
TreeSet():根据其元素的自然排序进行排序
-
TreeSet(Comparator comparator) :根据指定的比较器进行排序
特点
-
存储的元素有序
-
没有带索引的方法,所以不能使用普通for循环遍历
-
由于是Set集合,所以不包含重复元素的集合
数据结构:采用的是红黑树的结构(本质上使用的是TreeMap的key部分)
常用的方法与HashSet一致,这里不在进行演示,主要是讲解其排序的特点
3) 、保存基本数据类型及字符串
1>、保存基本数据类型
import java.util.Set;
import java.util.TreeSet;public class TreeSetDemo01 {public static void main(String[] args) {Set<Integer> set = new TreeSet<>();set.add(5);set.add(4);set.add(2);set.add(1);set.add(3);set.add(3);// 不能保存重复的元素System.out.println(set);// 保存的元素有序}
}
2>、保存字符串类型
import java.util.Set;
import java.util.TreeSet;public class TreeSetDemo02 {public static void main(String[] args) {Set<String> set = new TreeSet<>();set.add("zhangsan");set.add("lisi");set.add("wangwu");set.add("zhaoliu");set.add("zhouqi");set.add("wangba");set.add("zhousan");// 不能存储重复的元素System.out.println(set);// 保存的元素有序}
}
3>、保存自定义类型
public class Student {private String name;private Integer age;public Student() {}public Student(String name, Integer age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}
}
import java.util.Set;
import java.util.TreeSet;public class TreeSetDemo03 {public static void main(String[] args) {Set<Student> set = new TreeSet<>();set.add(new Student("zhangsan", 21));set.add(new Student("lisi", 19));set.add(new Student("wangwu", 18));set.add(new Student("wangba", 23));System.out.println(set);// 保存的元素有序}
}
异常为:java.lang.ClassCastException: com.woniu.treeset.Student cannot be cast to java.lang.Comparable。
类型转换异常,说是Student 不能 转换为 Comparable。Comparable在我们的代码里面没有涉及到,为什么会出现这个问题呢?Integer,String也是引用类型,我们在使用的时候没有出现这异常呢。
所以,我们来看一下String的源码
3、自然排序compareble:
comparable : 自然排序。是一个接口,只提供了一个方法:compareTo。就是排序的比较规则。如果使用TreeSet的无参构造方法保存自定义数据类型,那么该类应该实现comparable 接口,重写compareTo方法
public interface Comparable<T> {// 返回值为0,表示两个元素相等// 返回值为正整数,表示大于// 返回值为负整数,表示小于public int compareTo(T o);
}
案例演示
需求:存储学生对象并遍历,创建TreeSet集合使用无参构造方法。
要求:按照年龄从小到大排序。
public class Student implements Comparable<Student>{private String name;private Integer age;public Student() {}public Student(String name, Integer age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Student stu) {// 排序的规则// this表示需要添加进来的元素 ---> set.add(new Student("lisi", 19)); 表示的是lisi// stu表示需要比较的对象,即已经存进集合里面的对象//System.out.println(stu.age + "---" + this.age);return this.age - stu.age;}
}
import java.util.Set;
import java.util.TreeSet;public class TreeSetDemo03 {public static void main(String[] args) {Set<Student> set = new TreeSet<>();set.add(new Student("zhangsan", 21));set.add(new Student("lisi", 19));set.add(new Student("wangwu", 18));set.add(new Student("wangba", 23));set.add(new Student("zhouqi", 21));System.out.println(set);// 保存的元素有序}
}
本电子书目录:《Java基础的重点知识点全集》