这里写目录标题
TreeSet Map 泛型
TreeSet
- TreeSet添加的元素必须排序 , 有两种排序方式 :
- 1 要添加的元素对应的类实现java.lang.Comparable接口 , 并实现compareTo方法
- 2 使用java.util.Comparator比较类 compare方法
- 如果要添加的元素这两种条件都符合 , 会优先执行Comparator比较类 ( compare方法)
- Comparable : 要添加的元素实现该接口并覆写compareTo方法
- Comparator : 常应用于(比如)integer(一般情况下都是又有的数据类型 , 而不是自己定义的)默认升序
- 如果想要使他降序 , 可以使用Comparator进行降序排序
- 如果添加的元素是我们写的 , 我们应该使用Comparable , 因为有利于扩展开发 , 其他人还可以使用Comparator实现新的排序功能
- 如果该类没有实现排序(没有实现Comparable)或者实现的排序不是我们想要的 , 这时我们需要使用Comparator进行排序
- @杜智慧
- @Date 2021年1月23日
*/
Comparator
下面展示一些 内联代码片
。
// A code block
var foo = 'bar';
@SuppressWarnings("unused")
public class Collection_Sort {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
@SuppressWarnings("rawtypes")
TreeSet treeSet = new TreeSet(new SortTree() {
});
@SuppressWarnings("rawtypes")
TreeSet treeSet_ = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Integer i1 = (Integer)o1;
Integer i2 = (Integer)o2;
return i2-i1;
}
});
// 添加数据
treeSet.add(1);
treeSet.add(12);
treeSet.add(11);
treeSet.add(3);
treeSet.add(5);
// treeSet_添加数据
treeSet_.add(1);
treeSet_.add(12);
treeSet_.add(11);
treeSet_.add(3);
treeSet_.add(5);
// 遍历 1 3 5 11 12 默认升序
// new SortTree() 自定义一个排序类 , 实现Comparator接口 , 并覆写compare方法 12 11 5 3 1
// 常应用于已有的数据类型
for (Object object : treeSet) {
System.out.print(object + " ");
}
System.out.println();
System.out.println("-------------------------------");
// new Comparator() 这是一个匿名内部类 , 直接在创建对象的地方直接重新覆写内部排序方法 , 最后的实现效果 , 与自己定义类是一样的
// 且要方便许多 , 一般情况下选择这种排序方法 (数据类型并非自己定义的情况下)
for (Object object : treeSet_) {
System.out.print(object + " ");
}
}
}
@SuppressWarnings("rawtypes")
class SortTree implements Comparator {
@Override
public int compare(Object o1, Object o2) {
// TODO Auto-generated method stub
Integer i1 = (Integer)o1;
Integer i2 = (Integer)o2;
return i2-i1;
}
}
下面展示一些 内联代码片
。
// A code block
var foo = 'bar';
public class Collection_Sort_List {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
// 实现按id排序 id一样就按照年龄排序
TreeSet treeSet = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Student s1 = (Student) o1;
Student s2 = (Student) o2;
if (s1.getId()<s2.getId()) {
return -1;
}else if (s1.getId()>s2.getId()) {
return 1;
}else {
return s1.getAge()-s2.getAge();
}
}
});
// 添加数据
treeSet.add(new Student(1, 19, "张三1"));
treeSet.add(new Student(2, 18, "张三2"));
treeSet.add(new Student(3, 16, "张三3"));
treeSet.add(new Student(3, 13, "张三4"));
treeSet.add(new Student(3, 18, "张三5"));
for (Object object : treeSet) {
System.out.println(object);
}
}
}
class Student {
// 学生类内部有三个私有属性
private int id;
private int age ;
private String name;
// 获取get和set方法
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 需要覆写toString方法
@Override
public String toString() {
return "Student [id=" + id + ", age=" + age + ", name=" + name + "]";
}
// 构造方法
public Student(int id, int age, String name){
this.id = id;
this.age = age;
this.name = name;
}
}
Comparable
下面展示一些 内联代码片
。
// 这是没有进行覆写的
public class Collection_Sort_01 {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
// 创建链表对象
ArrayList arrayList = new ArrayList();
// 添加数据
arrayList.add(2);
arrayList.add(22);
arrayList.add(12);
arrayList.add(5);
// 没有排序的顺序 : 2 22 12 5
// 要注意 这里是Collections 能够使用这个方法来对链表进行排序操作
//是因为 , ArrayList这个类实现了Comparable接口
Collections.sort(arrayList);
// 2 5 12 22
for (Object object : arrayList) {
System.out.print(object+ " ");
}
}
}
下面展示一些 内联代码片
。
// 这是进行覆写的
public class Collection_Sort_02 {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
// 创建链表对象
ArrayList arrayList = new ArrayList();
// 添加数据
arrayList.add(2);
arrayList.add(22);
arrayList.add(12);
arrayList.add(5);
// 没有排序的顺序 : 2 22 12 5
// 要注意 这里是Collections 能够使用这个方法来对链表进行排序操作
//是因为 , ArrayList这个类实现了Comparable接口
Collections.sort(arrayList , new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Integer i1 = (Integer)o1;
Integer i2 = (Integer)o2;
return i2 - i1; // 降序
}
});
for (Object object : arrayList) {
System.out.println(object);
}
}
}
Map
- Map是无序可重复的 , 这里的可重复指的是value值可以重复
- key依旧不可重复(但是实际上我们存入的数据就只在value里 , key只是为hashCode算法提供一个载体)
- Map 的操作与 集合基本一致 ,
- put(Object key , Object value) : 向Map中添加键值对 返回值为Object
- size() : 个数 返回值为int
- clear() : 清空 返回值类型为void
- isEmpty() : 判断是否是空 返回值是boolean
- values() : 获取map中所有value值并以集合的形式返回所有的value值 返回值类型为Collection
- get(Object key) : 通过key获取value
- containsKey(Object key) : 判断是否包含某个key 返回值为Boolean类型
- containsValue(Object value) : 判断是否包含某个value 返回值为Boolean类型
- keySet() : 获取map中的所有key , 以Set集合的形式返回
- entrySet() : 返回map中的键值对映射关系 , 以Set集合的形式返回
- remove(Object key) : 根据key删除指定映射关系 , 返回value值
- map不能直接遍历 , 但是可以通过keySet等方法间接遍历
基本方法
public class Map_01 {
public static void main(String[] args) {
Map map = new HashMap();
map.put(“A”, “one”);
map.put(“B”, “two”);
map.put(“C”, “three”);
map.put(1003, “rose”);
map.put(‘A’, 1000);
map.put(65, 1000);
map.put("‘A’", 1000);
map.put(“A”, 3000); // 这个键值对里的value值会将第一个里的value值覆盖
// 支持 key和 value 都是null,但是没什么意义,并且只能有一个key为null
map.put(null, null);
// 8
System.out.println(map.size());
// 这八个值里的第一个A中的value值被覆盖了
Set e = map.keySet();
for (Object object : e) {
System.out.print(object +" ");
}
System.out.println();
// 调用"1003"的hashCode值,然后进行hash 得到数组下标
// 用该对象调用equals方法,和数组中链表的所有对象的key进行比较
// 此对象为 字符串1003 而 map中 没有,只有一个Integer的1003
// false
System.out.println(map.containsKey(“1003”));
// 只能去挨个遍历比较
// true
System.out.println(map.containsValue("rose"));
// 先根据"C" 调用HashCode 然后进行hash,得到数组下标,挨个和链表中对象进行equals比较
// 找到对应的对象后,获取其value值
// three
System.out.println(map.get("C"));
System.out.println("========");
// 获取所有的value 并遍历
Collection c = map.values();
for (Object object : c) {
System.out.println(object);
}
// 根据key,删除指定键值对,并返回value值
// three
System.out.println(map.remove("C"));
System.out.println("------------------");
// 把map中所有的key取出,返回set
Set keys = map.keySet();
for (Object key : keys) {
System.out.println(key+" : "+map.get(key));
}
System.out.println("====");
// 把键值对封装到entry中并以set形式返回
Set entrys = map.entrySet();
for (Object object : entrys) {
// 转换为Entry类型
Entry entry = (Entry) object;
System.out.println(entry.getKey()+" : "+entry.getValue());
}
}
}
特殊的Map
下面展示一些 内联代码片
。
强制规定键和值都是字符串
public class Map_02 {
public static void main(String[] args) {
Properties p = new Properties();
p.setProperty("key", "value");
// 可以输入两个值 , 第二个值可以不输入
// 如果有这个key 会输出他对于的value
System.out.println(p.getProperty("key"));
// 如果没有 , 会输出null
System.out.println(p.getProperty("ke"));
// 但是我们可以人为规定找不到输出什么 , 第二个值如果输入进去 , 找不到key就会输出这个nothing
System.out.println(p.getProperty("ke" , "nothing"));
}
}
SortedMap
下面展示一些 内联代码片
。
* SortedMap是一个接口 , 子实现是TreeMap , 元素必须有序 , 他会按照某个规定排序
*
* 实现排序的原因 :
* 1 被添加的元素 , 实现了Comparable接口
* 2 按照需求 , 编写一个比较器类 , 这个类需要实现Comparator接口并覆写compare方法
public class Map_SortedMap {
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args) {
TreeMap map = new TreeMap();
// new Comparator() {
//
// @Override
// public int compare(Object o1, Object o2) {
// Integer i1 = (Integer)o1;
// Integer i2 = (Integer)o2;
// return i2-i1;
// }
// }
// 因为TreeMap实现了Comparable接口 , 所以默认升序
// 1 5 12 13
// 可以直接new Comparator , 写一个匿名内部类
map.put(1, 2);
map.put(12, 2);
map.put(13, 2);
map.put(5, 2);
Set set = map.keySet();
for (Object object : set) {
System.out.print(object + " ");
}
}
}
下面展示一些 内联代码片
。
使用Comparable实现
public class Map_SortedMap_02 {
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args) {
TreeMap map = new TreeMap();
// new Comparator() {
//
// @Override
// public int compare(Object o1, Object o2) {
// Integer i1 = (Integer)o1;
// Integer i2 = (Integer)o2;
// return i2-i1;
// }
// }
// 因为TreeMap实现了Comparable接口 , 所以默认升序
// 1 5 12 13
// 可以直接new Comparator , 写一个匿名内部类
// 自定义的类 , 一般实现Comparable接口来排序
// 创建三个自定义类型的对象
Sort p1 = new Sort("大白菜", 3.5);
Sort p2 = new Sort("大葱", 8.0);
Sort p3 = new Sort("土豆", 2.2);
Sort p4 = new Sort("土", 2.2);
// key表示商品 value表示购买数量
// 将这些对象存入map中
map.put(p1, 3);
map.put(p2, 3);
map.put(p3, 1);
Set keys = map.keySet(); // 所有的key
for (Object key : keys) {
// 将存放在map里的key强制转换为Integer类型并存放在value里
int value = (Integer)map.get(key);
//将所有的key强制转换为sort类型(自定义的数据类型)
// key经历了两次强制类型转换 , 因为他不能直接转换为Sort类型
Sort sort = (Sort)key;
String name = sort.getName();
Double price = sort.getPrice();
System.out.println(name +"/"+price+" 每kg"+ " , 购买了 " + value+" kg , 共 : "+(price*value)+"元 ");
}
}
}
// 比较类 实现Comparable
class Sort implements Comparable{
private String name;
private double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
// 覆写toString方法
@Override
public String toString(){
return "Product [name=" + name + ", price=" + price + "]";
}
@Override
// 按照价格排序 , 如果价格相同不添加
public int compareTo(Object o) {
Sort s = (Sort)o;
if (this.price>s.price) {
return 1;
}else if (this.price<s.price) {
return -1;
}else {
return 0; // 如果相等不添加
}
}
public Sort(String name, double price) {
super();
this.name = name;
this.price = price;
}
}
泛型
- 泛型 : 集合与数组一样 , 只有一种类型 , 但是他却可以存储所有类型的数据 , 原因在于所有的数据类都继承了
- Object类 , 所以 , 所有的数据都可以发生向上转型(可以看作自定类型转换) , 于是他就可以存储所有的数据类型了
- 虽然他不能存储基本数据类型 , 但是他可以存包装类 , 但是这样虽然能够存储任意类型,但是使用起来就不方便了
- 在某种情况下 , 取出数据之后一定要向下转型才能使用
- 引入泛型之后,我们可以指定存储的类型,那么编译器在编译阶段,就会检查添加的数据的类型是否匹配,不匹配就报错
- 泛型只能是引用数据局类型,不能是基本数据类型 , 所以想要在使用基本数据类型时使用泛型 , 需要先装箱
- 优点 : 统一了数据类型,减少数据类型转换
- 缺点 : 只能存储单一类型的元素
- 就是在集合声明的时候指定了该集合的数据类型,指明了类型之后,再向集合中添加数据的时候,编译器就会对数据类型进行校验
- 下面展示一些
内联代码片
。
// A code block
var foo = 'bar';
public class Generic_01 {
public static void main(String[] args) {
// 不使用泛型
Set s = new HashSet();
A a = new A();
B b = new B();
C c = new C();
s.add(a);
s.add(b);
s.add(c);
// 使用的时候,就需要向下转型
for (Object object : s) {
if (object instanceof A) {
// 向下转型 , 强制类型转换
A a1 = (A) object;
a1.m1();
}else if (object instanceof B) {
B b1 = (B) object;
b1.m2();
}else if (object instanceof C) {
C c1 = (C) object;
c1.m3();
}
}
}
}
class A{
public void m1(){
System.out.println("---");
}
}
class B{
public void m2(){
System.out.println("11111");
}
}
class C{
public void m3(){
System.out.println("====");
}
}
下面展示一些 内联代码片
。
// A code block
var foo = 'bar';
public class Generic_04 {
public static void main(String[] args) {
MyClass mc = new MyClass();
mc.m1(2); // 默认是Object , 想传什么就穿什么
mc.m1("2"); // 默认是Object , 想传什么就穿什么
mc.m1('1'); // 默认是Object , 想传什么就穿什么
MyClass<Integer> class_01= new MyClass();
// class_01.m1(a); // 存别的类型直接报错
class_01.m1(1);
}
}
//T就相当于是个标签,占位符
//就是这里需要客户端(main方法)传递一个类型,用传递的类型替换这个T
//如果你不传,默认是Object
class MyClass<T> {
public void m1(T t) {
System.out.println(t);
}
}