TreeSet Map 泛型

这里写目录标题

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);
	}
}
上一篇:Set接口,数据结构


下一篇:Set、HashSet、TreeSet