Day16 Set、比较器、泛型 (部分)

本文详细介绍了Java集合框架中的TreeSet数据结构,包括其无序不可重复的特性,以及底层的红黑树实现。重点讲解了TreeSet如何通过Comparable和Comparator进行排序,以及泛型在集合中的应用,强调了泛型在类型检查和统一数据类型方面的优势。示例代码展示了如何自定义比较器和泛型的使用方法。
摘要由CSDN通过智能技术生成

Day16 Set、比较器
数据结构

  1. 集合
    1.1 Set
    无序不可重复
    TreeSet : 底层是红黑树(保证元素按照某种顺序排序)
    HashSet : 底层是散列

1.1.1 TreeSet
1.1.1.1 概述
java.util.SortedSet
java.util.TreeSet : 会按照某种顺序进行排序
数字 : 从小到大
字符串 : 每位的ASCII
日期 : 自然日期

比较器有两种
	要添加的元素实现比较器
	专门准备一个比较器类(优先级高)

进行排序的时候,根据比较器方法的返回值进行比较
如果是0 说明重复,不添加,如果是大于0的,说明元素大,往后放
如果是小于0的,说明要添加的元素小,往前放
1.1.1.2 基本使用
public static void main(String[] args) {
//调用TreeSet工具
Set set=new TreeSet();
//add()方法添加数据(每次添加数据都会调用比较器,如果相同就不添加)
set.add(1);
set.add(2);
set.add(2);
set.add(2);
//打印set,且输出结果为 1 2
System.out.println(set);
//删除数据 2
set.remove(2);
System.out.println(set);
set.add(56);
//查找seta中是否含有数据56
System.out.println(set.contains(56));
//打印set长度
System.out.println(set.size());
//清楚set中所有数据
set.clear();
System.out.println(set);
}
1.1.1.3 注意
如果要使用treeSet 那么 元素必须有比较器,两种都可以
否则就会有类型转换异常
1 要添加的原始 实现 java.lang.Comparable接口 并实现compareTo方法
2 写一个比较器类,实现java.util.Comparator比较器接口

很多常用的类中都实现了Comparable接口 并实现compareTo方法
比如 Integer , String , Date等

所以我们自定义类型的时候,一定要弄比较器类

1.1.2 比较器
可以让集合中的元素按照某个规则进行排序
在源码中体现了,先判断是否有compare() 如果没有再判断是否有compareTo()

所以 Comparator优先级要高于Comparable
1.1.2.1 Comparable
也可以叫元素自身比较器,就是要添加的元素需要实现这个接口,一般在我们的自定义类中常用
因为这种方式,直接让要添加的元素类实现接口就可以,编码方便,而Comparator需要单独写比较器类
因为它优先级低,我们给出的排序规则,如果不满足调用处,它还可以根据Comparator进行排序扩展
此时当调用处进行排序扩展的时候,此时Comparator和Comparable同时存在,则Comparator优先级高,所以最终排序规则会按照调用处指定的规则进行排序
public static void main(String[] args) {
Set set=new TreeSet();
set.add(new User(12, “colonel”));
set.add(new User(12, “colonel”));
set.add(new User(13, “colonel”));
set.add(new User(12, “General”));
set.add(new User(12, “colonel”));
System.out.println(set);
}
}
class User implements Comparable{
int age;
String name;

//有参构造方法
public User(int age, String name) {
	super();
	this.age = age;
	this.name = name;
}

@Override
public String toString() {
	return "User [age=" + age + ", name=" + name + "]";
}


@Override
public int compareTo(Object o) {
	//判断类型是否为 User 的对象,或者是其直接或间接子类,或者是其接口的实现类
	if (o instanceof User) {
		//强制类型转换
		User user=(User) o;
		//保存按照年龄排序的结果
		int result=age-user.age;
		//如果年龄相同,就比较名字,如果名字也相同就不添加
		if (result==0) {
			if (name.equals(user.name)) {
				return 0;
			}else {
				return 1;
			}
		}
		return result;
	}
	return 0;
}

1.1.2.2 Comparator
1 该类有排序(比如Integer实现了Comparable,并且是升序),但是排序规则不是我们想要的,这个时候需要使用Comparator来进行调整排序,因为优先级高
2 如果该类没有排序(没有实现Comparable接口),该类也不是我们写的,如果此时需要排序,则需要使用Comparator来完成

public static void main(String[] args) {
//不实现比较器的情况下默认升序排序
Set set =new TreeSet();
set.add(1);
set.add(1);
set.add(12);
set.add(6);
set.add(13);
System.out.println(set);
//传入比较器的情况下按照需求进行排序
Set set1 =new TreeSet(new IntegerCompartor());
set1.add(1);
set1.add(1);
set1.add(12);
set1.add(6);
set1.add(13);
System.out.println(set1);
}
}
class IntegerCompartor implements Comparator{
//实现Comparator 已达到降序的目的
@Override
public int compare(Object o1, Object o2) {
Integer i1=(Integer) o1;
Integer i2=(Integer) o2;
return i2-i1;
}

1.1.3 List排序
static ArrayList list =new ArrayList();
System.out.println(“请输入要添加的数量”);
//接收用户输入的数量
int n=scanner.nextInt();
//动态生成数组的长度
cattle=new Cattle[n];
//创建索引
int index=0;
//如果索引大于等于数量结束循环
creartCattle(n, index);
//根据年龄排序
Collections.sort(list);
//遍历集合
for (Object object : list) {
System.out.println(object);
}
所以 如果保存我们自定义类型,想要排序,必须有一个比较器类
根据需求决定用哪一种即可

1.2 泛型
1.2.1 概述

类型检查,编译过程中检查类型是否匹配
泛型 是在编译阶段对数据的类型进行匹配

优点 : 统一了数据类型,减少强制类型转换

缺点 : 只能存储单一类型的数据

结合我们的需求情况,绝大部分情况都是需要保存统一类型的数据,所以大部分情况下,使用泛型要好很多

泛型 只能是引用类型,不能是基本类型
1.2.2 基本使用

public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(“xxx”);

	List<Integer> nums = new ArrayList<Integer>();
	nums.add(11);
	// 由于指定了泛型,所以只能保存Integer类型
	// nums.add("xx");
	
	list = new ArrayList();
	list.add(new A());
	list.add(new B());
	list.add(new C());
	for (Object obj : list) {
		if (obj instanceof A) {
			A a = (A)obj;
			a.m1();
		}else if (obj instanceof B) {
			B b = (B)obj;
			b.m2();
		}
	}
	
	List<A> as = new ArrayList<A>();
	as.add(new A());
	for (A a : as) {
		a.m1();
	}
	
}

1.2.3 自定义泛型
泛型本质就是一个占位符,由调用处对这个占位符赋值

如果不赋值,默认是Object

常见的占位符 :
? : 表示不确定的类型
T : 表示一个具体的java类型 Type
K : 表示key ,java中的键值对
V : 表示value,
E : 表示Element,元素,集合中的数据我们叫元素

用什么字母都是可以的,一般都是大写,只是占位符而已

自定义泛型
class MyClass{

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值