DAY15-泛型,HashSet,TreeSet

今日内容:泛型,HashSet,TreeSet

Collection接口只定义了增,删,判断,遍历方法没有定义改查方法!

泛型类

class 类名<T,E,Y>//泛型类创建的时候可以不确定,等到创建对象的时候在确定,泛型可以为多个
import java.util.ArrayList;


class Person {
}

class Student extends Person {
}

class Teacher extends Person {
}
//泛型通配符,占位符,限定界限,注意泛型没有多态,不能前后不一致
public class Demo1 {
	public static void main(String[] args) {
		ArrayList<Person> l1=new ArrayList<>();
		l1.add(new Person());
		l1.add(new Student());//多态
		l1.add(new Teacher());//多态
		ArrayList<Student> l2=new ArrayList<>();
		ArrayList<Teacher> l3=new ArrayList<>();
		print(l1);
		print(l2);
		print(l3);
	}

	public static void print(ArrayList<? extends Person> list){//如果此处是extendsPerson则上面三个print都可以
//		public static void print(ArrayList<? super Student> list){//如果此处是supersPerson则Teacher用不了

	}
}

import java.util.Comparator;
import java.util.TreeSet;
//comparator后面的泛型在实现的时候要具体指出是哪一个,因为是Person2对象的比较,所以此处写Person2
/*什么时候用comparable什么时候用Comparator?二者其实作用相同,comparator是comparable的子接口,
comparator是创建TreeSet是的构造器中带的方法,此时需要用comparator,还有就是comparable中已经写好了按照自然顺序/字典顺序排序
不能随便更改,不然就要改源码,比较麻烦,适合可以直接适用自然排序的数据类型使用*/
//class Person2 implements Comparator<Person2> {
//	int age;
//	String name;
//	public Person2(){}	//一定要写一个无参构造函数,方便下面用这个类创建对象,否则就只能带参数创建对象,比较麻烦
//	public Person2(String name,int age){
//		this.name=name;
//		this.age=age;
//	}
//	@Override
//	public String toString() {
//		return name+"---"+age;
//	}
//	@Override
//	public int compare(Person2 p1, Person2 p2) {
//		int num=p1.age-p2.age;
//		if(num==0){
//			return p1.name.compareTo(p2.name);
//		}
//		return num;
//	}
//}
//public class Demo3 {		//TreeSet
//	public static void main(String[] args) {
/*TreeSet(Comparator<? super E> comparator) 构造一个新的空 TreeSet,它根据指定比较器进行排序。
下面使用了匿名内部类,父接口创建实现类对象,comparator不能直接创建对象,要使用他的实现类,所以直接把他的实现类
Person2中的compare方法重写一遍,这样就相当于创建了comparator对象,或者直接像下面那样创建Person2的对象*/
//		TreeSet<Person2> ts=new TreeSet<>(new Comparator<Person2>(){	
//			public int compare(Person2 p1, Person2 p2) {
//				int num=p1.age-p2.age;
//				if(num==0){
//					return p1.name.compareTo(p2.name);
//				}
//				return num;
//			};
//		});
//		
//		TreeSet<Person2>ts=new TreeSet<>(new Person2());//如果上面没写无参构造函数那么创建对象就只能写成new Person2("",2)
//		ts.add(new Person2("zhangsan",20));
//		ts.add(new Person2("lisi",21));
//		ts.add(new Person2("wangwu",20));
//		ts.add(new Person2("zhaoliu",24));
//		ts.add(new Person2("heqi",20));
//		
//		for(Object obj:ts){
//			Person2 p=(Person2)obj;//Object是父类,但是name和age是子类特有的,所以要向下转型
//			System.out.println(p);
//		}
//	}
//}
//下面用comparable方法,很简便
class Person3 implements Comparable<Person3>{
	int age;
	String name;
	public Person3(){}
	public Person3(String name,int age){
		this.name=name;
		this.age=age;
	}
	@Override
	public String toString() {
		return name+"-----"+age;
	}
	@Override
	public int compareTo(Person3 p) {
		int num=this.age-p.age;
		if(num==0){
			return this.name.compareTo(p.name);//此处调用的是String类中的compareTo方法
		}
		return num;
	}
}

public class Demo3{
	public static void main(String[] args) {
		TreeSet<Person3> x=new TreeSet<>();
		x.add(new Person3("zhangsan",20));
		x.add(new Person3("lisi",21));
		x.add(new Person3("wangwu",20));
		x.add(new Person3("zhaoliu",24));
		x.add(new Person3("heqi",20));
		for(Object obj:x){
			Person3 y=(Person3)obj;//Object是父类,但是name和age是子类特有的,所以要向下转型
			System.out.println(y);
		}
	}
}

HashSet

import java.util.HashSet;
import java.util.Set;

class Person{
	int age;
	String name;
	public Person(String name,int age){
		this.name=name;
		this.age=age;
	}
	@Override
	public String toString() {
		return "姓名:"+name+"---"+"年龄"+age;
	}
//	@Override
//	public int hashCode() {
//		System.out.println("----");//先判断了hashcode方法
//		return 100;
//	}
///*先执行一次hashcode,直接放进去,然后在执行一次hashcode,发现有相同的,执行equals方法,判断是不同对象,存进去,
//然后再计算hashcode,相同,执行equals方法2次,与前面已经存进去的两个元素相比较,发现不是同一元素,存进去,循环直到
//所有元素都执行过了为止*/
//	@Override
//	public boolean equals(Object obj) {
//		System.out.println("****");
//		return super.equals(obj);
//	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)//判断地址值,相同说明是堆内存中的同一个元素
			return true;
		if (obj == null)//对象才能调用方法,空对象不能调用方法,所以如果obj是null的话二者就不相等
			return false;
		if (getClass() != obj.getClass())//!(obj instanceof Person)
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
}
public class Demo2 {
	public static void main(String[] args) {
		// set方法
		Set<Person> a = new HashSet<>();//泛型
		a.add(new Person("张三",20));
		a.add(new Person("张四",21));
		a.add(new Person("张五",22));
		a.add(new Person("张四",21));
		a.add(new Person("张三",20));
		for (Person per : a) {
			System.out.println(per);
		}
	}
}

TreeSet

TreeSet集合中保存对象的时候:

  1. 如果多个不同类型的对象他们之间没有继承关系,这是是不能同时存储到同一个TreeSet集合中的
  2. 如果多个不同类型的对象,他们之间有继承关系,并且父类已经实现了Comparable接口,这时这些父类对象和子类对象都可以在TreeSet集合中保存。
import java.util.TreeSet;

/*什么时候用comparable什么时候用Comparator?二者其实作用相同,comparator是comparable的子接口,
comparator是创建TreeSet时的构造器中带的方法,此时需要用comparator,还有就是comparable中已经写好了按照
自然顺序/字典顺序排序不能随便更改,不然就要改源码,比较麻烦,适合可以直接适用自然排序的数据类型使用*/
//comparator后面的泛型在实现的时候要具体指出是哪一个,因为是Person2对象的比较,所以此处写Person2
//class Person2 implements Comparator<Person2> {
//	int age;
//	String name;
//	public Person2(){}	//一定要写一个无参构造函数,方便下面用这个类创建对象,否则就只能带参数创建对象,比较麻烦
//	public Person2(String name,int age){
//		this.name=name;
//		this.age=age;
//	}
//	@Override
//	public String toString() {
//		return name+"---"+age;
//	}
//	@Override
//	public int compare(Person2 p1, Person2 p2) {
//		int num=p1.age-p2.age;
//		if(num==0){
//			return p1.name.compareTo(p2.name);
//		}
//		return num;
//	}
//}
//public class Demo3 {		//TreeSet
//	public static void main(String[] args) {
/*TreeSet(Comparator<? super E> comparator) 构造一个新的空 TreeSet,它根据指定比较器进行排序。
下面使用了匿名内部类,父接口创建实现类对象,comparator不能直接创建对象,要使用他的实现类,所以直接把他的实现类
Person2中的compare方法重写一遍,这样就相当于创建了comparator对象,或者直接像下面那样创建Person2的对象*/
//		TreeSet<Person2> ts=new TreeSet<>(new Comparator<Person2>(){	
//			public int compare(Person2 p1, Person2 p2) {
//				int num=p1.age-p2.age;
//				if(num==0){
//					return p1.name.compareTo(p2.name);
//				}
//				return num;
//			};
//		});
//		
//		TreeSet<Person2>ts=new TreeSet<>(new Person2());//如果上面没写无参构造函数那么创建对象就只能写成new Person2("",2)
//		ts.add(new Person2("zhangsan",20));
//		ts.add(new Person2("lisi",21));
//		ts.add(new Person2("wangwu",20));
//		ts.add(new Person2("zhaoliu",24));
//		ts.add(new Person2("heqi",20));
//		
//		for(Object obj:ts){
//			Person2 p=(Person2)obj;//Object是父类,但是name和age是子类特有的,所以要向下转型
//			System.out.println(p);
//		}
//	}
//}
//下面用comparable方法,很简便
class Person3 implements Comparable<Person3>{
	int age;
	String name;
	public Person3(){}
	public Person3(String name,int age){
		this.name=name;
		this.age=age;
	}
	@Override
	public String toString() {
		return name+"-----"+age;
	}
	@Override
	public int compareTo(Person3 p) {
		int num=this.age-p.age;
		if(num==0){
			return this.name.compareTo(p.name);//此处调用的是String类中的compareTo方法
		}
		return num;
	}
}

public class Demo3{
	public static void main(String[] args) {
		TreeSet<Person3> x=new TreeSet<>();
		x.add(new Person3("zhangsan",20));
		x.add(new Person3("lisi",21));
		x.add(new Person3("wangwu",20));
		x.add(new Person3("zhaoliu",24));
		x.add(new Person3("heqi",20));
		for(Object obj:x){
			Person3 y=(Person3)obj;//Object是父类,但是name和age是子类特有的,所以要向下转型
			System.out.println(y);
		}
	}
}
import java.util.ArrayList;

public class Demo4 {
	public static void main(String[] args) {
		//创建一个容器
		ArrayList<String> list1=new ArrayList<>();//泛型
		list1.add("a");
		list1.add("b");
		list1.add("c");
		list1.add("d");
		list1.add("e");
		list1.add("a");
		list1.add("b");
		list1.add("c");
		ArrayList<String> list2=quChong(list1);//调用方法,静态的,可以直接调用,非静态的话就创建对象
		System.out.println(list2);
	}
	//创建一个用来去重的方法,注意要使用静态的,方便直接调用,因为主方法是静态的
	public static ArrayList<String> quChong(ArrayList<String> a){
		ArrayList<String> newList=new ArrayList<>();
		for(Object obj:a){//foreach遍历集合
			String x=(String)obj;//需要类型转换,foreach遍历默认的是Object类的
			if(!newList.contains(x))
				newList.add(x);
		}
		return newList;
	}
}
import java.util.ArrayList;

public class Demo5 {
//把集合中的元素都转换成大写
	public static void main(String[] args) {
		ArrayList<String> a=new ArrayList<>();
		a.add("aBc123");
		a.add("cde");
		a.add("ert");
		a.add("seT");
		a.add("vvv");
		//调用方法
		big(a);
	}
	public static void big(ArrayList<String> d){
		for (String s:d) {
//String是一个存放在常量池里的,如果没有引用指向他,他就会变成垃圾被回收,所以不能写s.toUppercaser然后在下一行里输出
//这样输出的还是没有改变的s,应该直接输出,或者定义一个变量来接收他
			String e=s.toUpperCase();
			System.out.println(e);
		}
	}
}
public class Demo6 {

	public static void main(String[] args) {
		AA<String> a = new AA<>();
		a.show("abc");
		a.show01(123);// 确定变量具体类型为integer
		AA.show02(new Demo6());
	}

	@Override
	public String toString() {
		return "hello";
	}
}

// 泛型类,成员变量只能是T类型的,可以同时定义多个泛类型
class AA<T> {// class AA<T,Y,E>
	T t;// 定义T类型的成员变量t

	public void show(T t) {// 泛型方法,可以与泛型类的变量要求相同
		System.out.println(t);
	}

	public <Y> void show01(Y y) {// 泛型方法,可以与泛型类的变量要求不同,申明的时候要写在void前面,在引用方法的时候确定下来具体类型
		System.out.println(y);
	}

	// 静态泛型方法,可以直接用类名调用,同样的在调用方法时确认具体类型,注意:他不能使用泛型类上定义的泛型变量,因为他
	// 是静态的,是先加载的,这个概念已经反复强调很多遍了
	public static <E> void show02(E e) {
		System.out.println(e);
	}
}

// 泛型接口
interface inter<T> {// 创建一个泛型接口
	abstract public void show(T t);// 可以使用这个泛型

	abstract public <Y> void method(Y y);// 也可以不使用这个泛型
}

class interimp implements inter<String> {//创建一个实现类,可以此时确定类型
	@Override
	public void show(String str) {//重写方法,确认T为String类型
		System.out.println(str);
	}
	@Override
	public <String> void method(String a) {//重写方法,注意void前面的<String>不能丢
		System.out.println(a);
	}
}
//可以先不用确定类型,等到创建实现类对象时再确认,但是类名后面也要跟一个泛型
class interimp1<T> implements inter<T>{

	@Override
	public void show(T t) {
	}

	@Override
	public <Y> void method(Y y) {//什么时候调用此方法什么时候确认类型
	}
}

Comparator和Comparable总结

**相同点:**他们都可以提供比较大小的方法;
不同点:
Comparable: 他是让某个类具备了比较功能,当创建出这个类的对象,就可以直接使用这个对象中的compareTo方法进行比较大小。Comparable是让对象自己具备了比较功能
Comparator: 他是提供比较两个对象大小,但是这个功能和对象自身并没有任何的关系。只要将需要比较的两个对象传递给compare方法即可。提供单独的比较器对象,可以比较任意的两个对象。

猜你喜欢

转载自blog.csdn.net/qq_42837554/article/details/88360848