1. Set 和排序
1.1 概述
set 特点: 无序、不可重复、添加顺序和取出顺序不一定一致。
Set --> SortedSet --> TreeSet :底层是红黑树,要添加的元素必须按照某个规则进行排序。
2 TreeSet
2.1 概述
set 特点: 无序、不可重复、添加顺序和取出顺序不一定一致。
Set --> SortedSet --> TreeSet :底层是红黑树,要添加的元素必须按照某个规则进行排序。
数字: 默认升序。 字符串:默认比较每一位的ASCII码值。 时间:默认自然日期(昨天,今天,明天)。
2.2使用
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TreeSet;
public class Test{
public static void main(String []args) throws ParseException{
//TreeSet对象创建
TreeSet trs = new TreeSet();
//添加数据
trs.add(1);
trs.add(5);
trs.add(4);
trs.add(2);
System.out.println(trs); //1 2 4 5
trs = new TreeSet();
trs.add("1");
trs.add("15");
trs.add("2");
trs.add("5");
System.out.println(trs); // 1 15 2 5
String strTime1 = "2021-12-02";
String strTime2 = "2020-01-22";
String strTime3 = "2024-06-12";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d1 = sdf.parse(strTime1);
Date d2 = sdf.parse(strTime2);
Date d3 = sdf.parse(strTime3);
trs = new TreeSet();
trs.add(d1);
trs.add(d2);
trs.add(d3);
System.out.println(trs);
}
}
2.3 为什么会排序? 其他类型可不可以?
为什么 String Integer Date 能排序, 其他的类型不行?
因为以上三种类型都实现了 Comparable 接口,并实现了 compareTo() 方法。
而往 TreeSet 中添加数据的时候,会自动调用该对象的 compareTo() 方法,因此它们可以排序。
但是如果我们想添加其他元素,尤其是自定义类型的时候,就不行了,需要我们自己实现 Comparable 接口, 实现compareTo() 方法。
import java.util.TreeSet;
public class Test{
public static void main(String[]args){
//创建TreeSet对象
TreeSet ts = new TreeSet();
//添加User类型数据
ts.add(new User (15));
ts.add(new User (22));
ts.add(new User (33));
System.out.println(ts);
}
}
class User implements Comparable{
int age;
@Override
public String toString() {
return "User [age=" + age + "]";
}
public User(int age) {
super();
this.age = age;
}
@Override
public int compareTo(Object o){
// this 是要要添加的元素 , o 是集合中的每一个元素
// 返回值为0 , 说明相等, 就不添加
// 返回小于0 的, 说明要添加的元素比集合中的元素小,就放到前面
// 返回大于0的,说明要添加的元素比集合中的元素大,就放到后面
if(o instanceof User){
User user = (User) o;
//升序
return this.age - user.age;
/*降序
return user.age - this.age.
*/
}
return -1;
}
}
3. 树
3.1 二叉查找树
类似于二分法查找,查询效率较高。
左叶子,永远都比根节点小。
右叶子,永远都比根节点大。
这种方式是二分查找的思想,查询所需要的最大次数,等同于二叉树的高度。
在添加数据的时候,也是类似的方式,一层层找一直找到适合的节点的位置。
缺点:
如果一直添加比根节点小,或者比根节点大的数据,这样会导致查询变慢。
3.2 红黑树
红黑树是一种自平衡的二叉查找树。
为了解决二叉树多次插入新节点而导致的不平衡,红黑树就诞生了。
完全符合二叉查找的特性:
1.节点是红色或者黑色。
2.根节点一定是黑色。
3.每个子节点都是黑色的空节点。
4.每个红节点的两个字节点都是黑色。
5.从任何节点到其每一个子节点都有相同数量的黑色节点。
4. 排序
4.1 概述
比较器类有两种:
1. java.lang.Comparable 接口, 并实现 compareTo()方法
2. java.util.Comparator 比较器类
4.2 Comparable
如果我们的自定义类型想要放到treeSet中,必须实现Comparable接口,否则就无法使用treeSet进行数据保存。
4.3 Comparator
4.3.1 概述
比如我们现在要保存数字,并且要求降序。
而 Integer 中,默认为升序,没法改变源码,可以使用 Comparator 解决该问题。 Comparator 的优先级 要大于 Comparable 。
4.3.2 使用
保村数字,并降序。
import java.util.Comparator;
import java.util.TreeSet;
public class Test{
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args){
//创建一个TreeSet对象
TreeSet ts = new TreeSet( new Comparator() {
@Override
public int compare(Object o1, Object o2) {
// o1是要添加的元素,o2是集合中的元素
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
// i1-i2是升序, i2-i1是降序
return i2 - i1;
}
} );
//添加数据
ts.add(15);
ts.add(21);
ts.add(6);
ts.add(33);
System.out.println(ts); //6 11 19 28
}
}
5.Collections
list 想要排序,元素必须实现 Comparable 接口。
如果元素自身没有实现 Comparable 接口,是不能调用 sort 方法的,会报错。
如果没有实现接口, 就可以使用 Comparator 方法,sort 方法可以进行重载,来接受 Comparator
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Test{
public static void main(String[]args){
//创建一个ArrayList对象
ArrayList al = new ArrayList();
//添加数据
al.add(5);
al.add(4);
al.add(8);
al.add(2);
Collections.sort(al, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i2 - i1;
}
});
System.out.println(al); // 8 5 4 2
}
}
6. 总结
自己添加元素时,可以实现 Comparable 接口。
如果后期需要重新排序,可以调用 Comparator 方法排序。
因为 Comparator 和 Comparable 同时存在的时候,Comparator 优先级要高。
7.HashSet
7.1 散列表
散列表,也叫哈希表。是根据关键码值直接访问的数据结构。 HashSet 的底层就是 HashMap 的 Key 部分,屏蔽了 HashMap 的 value 值。
1.调用 Key 的 hashCode 方法生成 hash 值。
2.散列存储方式。
3.生成数组索引。
4.判断数组对应的索引中是否有节点
5.没有节点直接添加
6.有节点,判断是否存在当前元素
7.如果链表中的节点个数大于等于8就转为树。
import java.util.HashSet;
public class Test05{
public static void main(String[]args){
//创建散列表对象
HashSet hs = new HashSet();
hs.add("a");
hs.add("c");
hs.add("e");
hs.add("g");
hs.add("j");
System.out.println(hs);
for(Object obj:hs){
System.out.println(obj);
}
}
}