1. Set
1.1 概述
Set特性 无序不可重复
无序 : 指的是添加顺序不保证有序
不可重复 : 不能添加重复数据
TreeSet : 底层是红黑树,添加的元素会按照一定格式进行自动排序
比如 数字 : 默认升序 , 12345
字符串 : 默认按照每一位ASCII码值进行排序
1 2 3 4 5 6 7 8 9 10
1 10 2 3 4 5 6 7 8 9
Date : 自然日期,昨天,今天,明天
HashSet : 底层是 HashMap,而HashMap底层是散列表
HashSet 是Map中的key部分
1.2 区别
1. List 和 Set 的区别:
List 有序可重复
Set 无序不可重复
2. ArrayList 和 LinkedList 的区别:
ArrayList : 查询快,底层是数组
LinkedList : 添加删除快,底层是双向链表
3. HashSet 和 TreeSet 的区别
HashSet : 底层是散列表
TreeSet : 底层是红黑树,元素必须有序
4. HashSet 和 TreeSet 的区别
Map 无序,key不能重复,value能重复,保存映射关系
HashMap : 底层是散列表
TreeMap : 底层是红黑树,元素必须有序
2. TreeSet
2.1 概述
TreeSet : 会自动排序,是因为,向treeSet中添加的数据,都有比较器
因此 我们如果要添加没有比较器的对象或者自定义的对象时,会出错
另外 因为排序需要比较,所以只能添加同类型数据
2.2 使用方法
Set set = new TreeSet();
// 重复后,不添加
// 添加会调用对象的equals方法,进行比较,重复不添加
set.add("a");
set.add("a");
set.add("a");
set.add("a");
set.add("a");
set.add("1");
set.add("b");
// 删除,根据内容删除
set.remove("a");
// 没有修改和查询
System.out.println(set);
// 个数
System.out.println(set.size());
// 判断是否为空(个数是否为0)
System.out.println(set.isEmpty());
// 判断是否包含某个元素
System.out.println(set.contains("x"));
// 清空
set.clear();
// 遍历
for (Object object : set) {
System.out.println(object);
}
int[] arr = {};
for (int i : arr) {
}
3. HashSet
使用方法
//Set set = new TreeSet();
Set set = new HashSet();
// 重复后,不添加
// 添加会调用对象的equals方法,进行比较,重复不添加
set.add("a");
set.add("a");
set.add("a");
set.add("a");
set.add("a");
set.add("1");
set.add("b");
set.add(23123);
// 删除,根据内容删除
set.remove("a");
// 没有修改和查询
System.out.println(set);
// 个数
System.out.println(set.size());
// 判断是否为空(个数是否为0)
System.out.println(set.isEmpty());
// 判断是否包含某个元素
System.out.println(set.contains("x"));
// 清空
set.clear();
// 遍历
for (Object object : set) {
System.out.println(object);
}
int[] arr = {};
for (int i : arr) {
}
4. 比较器
4.1 Comparable
使用TreeSet的时候,元素必须实现了Comparable接口,因为在添加的时候,会自动调用该接口的compareTo方法进行比较
添加字符串,数字,日期的时候,会进行自动排序,是因为Integer,String,Date都实现了该接口和该方法
如果我们要存储自定类型的时候,就需要让该类去实现对应的接口和方法才能进行存储
比较器之 Comparable , 被添加的元素,需要实现 Comparable 接口,并覆写 接口中的 compareTo()方法
compareTo方法返回值代表排序规则,
添加元素时,会用要添加的元素对象调用compareTo方法,把集合中的元素传入进行比较
如果是0 ,说明重复,不添加,
如果小于0,说明要添加的元素小,往前放,
如果大于0 ,说明要添加的元素大,往后放
4.2 使用方法
public static void main(String[] args) {
Set set = new TreeSet();
set.add(new Student("张三",18));
set.add(new Student("张四",19));
set.add(new Student("张五",17));
System.out.println(set);
}
}
class Student implements Comparable{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
}
public Student(String name) {
super();
this.name = name;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Object o) {
// this 代表 当前要添加的元素
// o 表示 集合中的元素
if (o instanceof Student) {
Student stu = (Student) o;
// 10 9 升序
return this.age - stu.age;
}
return 0;
}
4.3 Comparator
Comparator : 比较器类,要添加的元素并不需要实现这个借口
使用场景:
1 比如 Integer中 默认有比较方法.并且是升序,假如我们想要降序的时候,此时没办法修改源码,所以可以通过Comparator来重新定义排序规则
2 我们想保存的数据,不能排序(没有实现Comparable接口),但是这个类也不是我们写的,比如 Object,想要把Object对象保存在treeSet中
我们还是没有办法去修改源码,还是需要Comparator 来进行比较
当保存的元素不能排序(没有实现Comparable接口)时, 或者 , 排序规则不符合我们的需求时,均使用Comparator 来解决
并且 当 Comparator 比较器 和 Comparable比较器 同时存在时,Comparator 优先级高于 Comparable
对修改关闭,对扩展开放
4.4 使用方法
public static void main(String[] args) {
Set set = new TreeSet(new Comparator() {
// 匿名内部类
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Integer && o2 instanceof Integer) {
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
// 降序
return i2 -i1;
}
return 0;
}
});
set.add(1);
set.add(5);
set.add(3);
set.add(4);
set.add(2);
System.out.println(set);
}
4.5 注意
以下情况,不适合使用Comparator,应该使用 Comparable
因为User类是我们写的,我们可以修改源码,如果此时我们使用Comparable的话,当排序规则不满足客户需求时,客户可以使用Comparator进行重写
当我们使用的类是其他类(非我们写的类)时,我们没办法 修改源码,此时 才使用 Comparator来解决
4.6 List排序
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(5);
list.add(3);
list.add(4);
list.add(2);
// Collections.sort(list);
Collections.sort(list, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Integer && o2 instanceof Integer) {
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i2 - i1;
}
return 0;
}
});
list.sort(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Integer && o2 instanceof Integer) {
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i2 - i1;
}
return 0;
}
});
System.out.println(list);
}
4.7 总结
Comparable : 如果treeSet中保存我们自己定义的类型的时候,使用Comparable
Comparator : 如果treeSet中保存的不是我们写的类型的时候,就要使用Comparator来指定排序规则
比如 Integer 默认是升序排序,假如我们需要降序排序,我们只能使用 Comparator,因为我们不可能去更改Integer的源码
但此时 Integer中是有Comparable接口的实现的,等于两个比较都存在,但是Comparator优先级高,
所以会按照我们定义的规则进行排序
开闭原则 : 对修改关闭,对扩展开发