黑马程序员--第十五天:泛型

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

 

/*15-1
Set: 元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。
	|--HashSet:底层结构是Hash表,线程非同步
		HashSet 是如何保证元素的唯一性的呢?
		是通过元素的两个方法,hashCode 和 equals来完成的。
		如果元素的hashcode值相同,才会判断equals是否为true;
		如果元素的hashcode值不相同,不会调用equals。
		
		
	|--TreeSet:可以对Set集合中的元素进行排序。
Set集合的功能和Collection是一致的。
*/

import java.util.Iterator;
import java.util.TreeSet;

class Demo{
	public static void main(String [] args){
		TreeSet ts  = new TreeSet();
		ts.add("Abc");
		ts.add("Dbc");
		ts.add("bbc");
		ts.add("acc");
		ts.add("abc");
		
		Iterator it = ts.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
	
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

import java.util.Iterator;
import java.util.TreeSet;


/*15-2_3
Set: 元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。
	|--HashSet:底层结构是Hash表,线程非同步
		HashSet 是如何保证元素的唯一性的呢?
		是通过元素的两个方法,hashCode 和 equals来完成的。
		如果元素的hashcode值相同,才会判断equals是否为true;
		如果元素的hashcode值不相同,不会调用equals。
		
		
	|--TreeSet:可以对Set集合中的元素进行排序。
				底层数据结构是二叉树。
				保证元素唯一性的依据是compareTo方法return0;
				
				TreeSet排序的第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,实现compareTo方法。
				这种方法也叫默认自然顺序,也叫默认顺序。
				
				TreeSet第二种排序方式:
				当元素自身不具备比较性时,或者具备的比较性不是所需的。
				这时就需要让集合自身具备比较性。
				在集合初始化时就有了比较方式。
				
				注意:当主要条件相同时,判断次要条件。
				
				
Set集合的功能和Collection是一致的。
*/

class Demo{
	public static void main(String [] args){
		TreeSet ts  = new TreeSet();
		
		ts.add(new Person("mike001", 22));
		ts.add(new Person("mike007", 29));
		ts.add(new Person("mike008", 29));
		ts.add(new Person("mike005", 33));
		ts.add(new Person("mike002", 18));
		
		
		Iterator it = ts.iterator();
		while(it.hasNext()){
			Person p = (Person) it.next();
			System.out.println(p.getName()+"..."+p.getAge());
		}
	}
	
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

class Person implements Comparable{//该接口强制 该类 具备比较性。
	private String name;
	private int age;
	
	Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	
	public String getName(){
		return name;
	}
	
	public int getAge(){
		return age;
	}

	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(!(obj instanceof Person))
			return false;
		Person p = (Person) obj;
		System.out.println(this.name+"...equals .."+p.name);
		return ((this.age == (p.age)) && (this.name.equals(p.name)));
	}

	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		if(!(o instanceof Object))
			throw new RuntimeException("对象不满足要求");
		Person p = (Person) o;
		System.out.println(this.name+"..."+p.getName());
		
		if(this.getAge()==p.getAge())
			return this.getName().compareTo(p.getName());
		return this.getAge() - p.getAge();
	}
}

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;


/*15-4
TreeSet第二种排序方式:
当元素自身不具备比较性时,或者具备的比较性不是所需的。
这时就需要让集合自身具备比较性。
在集合初始化时就有了比较方式。

定义比较器(定义一个类,实现Comparator接口,覆盖compare方法),将比较器对象作为参数传递给TreeSet集合的构造函数。

当两种排序都存在时,以比较器为主。
*/

class Demo{
	public static void main(String [] args){
		TreeSet ts  = new TreeSet(new MyCompare());
		
		ts.add(new Person("mike001", 22));
		ts.add(new Person("mike007", 29));
		ts.add(new Person("mike008", 29));
		ts.add(new Person("mike005", 33));
		ts.add(new Person("mike002", 18));
		ts.add(new Person("mike002", 28));
		
		
		Iterator it = ts.iterator();
		while(it.hasNext()){
			Person p = (Person) it.next();
			System.out.println(p.getName()+"..."+p.getAge());
		}
	}
	
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

class MyCompare implements Comparator{

	@Override
	public int compare(Object o1, Object o2) {
		// TODO Auto-generated method stub
		
		Person p1 = (Person) o1;
		Person p2 = (Person) o2;
		int num = p1.getName().compareTo(p2.getName());
		
		if (num == 0)
			return Integer.valueOf(p1.getAge()).compareTo(Integer.valueOf(p2.getAge()));
		return num;
	}
	
}


//不修改Person类前提下,改变比较方法************************
class Person implements Comparable{//该接口强制 该类 具备比较性。
	private String name;
	private int age;
	
	Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	
	public String getName(){
		return name;
	}
	
	public int getAge(){
		return age;
	}

	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(!(obj instanceof Person))
			return false;
		Person p = (Person) obj;
		System.out.println(this.name+"...equals .."+p.name);
		return ((this.age == (p.age)) && (this.name.equals(p.name)));
	}

	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		if(!(o instanceof Object))
			throw new RuntimeException("对象不满足要求");
		Person p = (Person) o;
		System.out.println(this.name+"..."+p.getName());
		
		if(this.getAge()==p.getAge())
			return this.getName().compareTo(p.getName());
		return this.getAge() - p.getAge();
	}
}

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;


/*15-5
练习:按字符串长度排序。
*/

class Demo{
	public static void main(String [] args){
		TreeSet ts  = new TreeSet(new StringLengthComparator());
		
		ts.add("a");
		ts.add("adf");
		ts.add("aa");
		ts.add("aaa");
		ts.add("aadf");
		ts.add("addf");
		
		
		Iterator it = ts.iterator();
		while(it.hasNext()){
			String s = (String) it.next();
			System.out.println(s.length()+"\t"+s);
		}
	}
	
	public static void sop(Object obj){
		System.out.println(obj);
	}
}


class StringLengthComparator implements Comparator{

	@Override
	public int compare(Object o1, Object o2) {
		// TODO Auto-generated method stub
		String s1 = (String) o1;
		String s2 = (String) o2;
		
		int num = s1.length()-s2.length();
		
		if(num == 0)
			return s1.compareTo(s2);
		return num;
	}
	
}


import java.util.ArrayList;
import java.util.Iterator;


/*15-6
泛型:JDK 1.5 新特性,用于解决安全问题,是一个类型安全机制。
好处:
1.将运行时期出现的问题ClassCastException,转移到了编译时期。
	方便于程序员解决问题。让运行时期问题减少,安全提高。
2. 避免了强制转换麻烦。

泛型格式:通过<>来定义要操作的数据类型。
在java提供的对象时,什么时候写泛型呢?
只要见到<>就要定义泛型。

其实<>就是用来接收类型的。

当使用集合时,将集合中要存储的类型做为参数传递到<>.
*/

class Demo{
	public static void main(String [] args){
		ArrayList<String> al  = new ArrayList<String>();
		
		al.add("ac");
		al.add("abc");
		al.add("abac");
		
		//al.add(5);//al.add(new Integer(4));
		//当在al中增加了数字时,会发生类型转换异常ClassCastException(数字 不能转换成String)。
		
		Iterator<String> it = al.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
	
	public static void sop(Object obj){
		System.out.println(obj);
	}
}



/*15-8
什么时候用泛型?
当类中要操作的引用数据类型不确定的时候。
早期定义Object来完成扩展。
现在定义泛型来完成扩展。
 */
class Worker
{
}

class Student
{
}

//泛型前做法
class Tool
{
	private Object obj;
	public void setObject(Object obj){
		this.obj = obj;
	}

	public Object getObject(){
		return obj;
	}
}

//泛型做法
class Utils<T>{
	private T t;
	public void setObject(T t){
		this.t = t;
	}
	
	public T getObject(){
		return t;
	}
}

class  Demo
{
	public static void main(String[] args) 
	{
		Tool t = new Tool();
		t.setObject(new Worker());
		t.setObject(new Student());
		Worker w = (Worker)t.getObject();
		System.out.println("Hello World!");
	}
}


//15-9
class Show<T>{//泛型类定义的泛型,在整个类中有效,如果被方法使用,
	//那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了
	//为了让不同的方法可以操作不同的类型,而且类型还不确定,
	//那么可以将泛型定义在方法上。
	//private T t;
	public void show(T t){
		System.out.println("show:" + t);
	}

	public void print(T t){
		System.out.println("print:" + t);
	}
	
}

class Show1{
	public <T> void show(T t){
		System.out.println("show:" + t);
	}

	public <T> void print(T t){
		System.out.println("print:" + t);
	}
	
}

class Show2<T>{
	public void show(T t){
		System.out.println("show:" + t);
	}
	
	public <E> void print(E t){
		System.out.println("print:" + t);
	}
	
}

//static方法不可以访问类定义的泛型
class Show3<T>{
	/*public static void show(T t){
		System.out.println("show:" + t);
	}*/ //编译报错,因为该方法的T 与类的T 是同一个参数
	//而 类的T 是在new对象的时候确定的,因此会报错。
	
	public static <T> void print(T t){//该处没有报错,因为这是定义在方法上的。
		System.out.println("print:" + t);
	}
	
}

class  Demo
{
	public static void main(String[] args) 
	{
		/*Show<String> s = new Show<String>();
		s.show("show");
		s.print(new Integer(5));//报错
		s.print("print");*/
		
		Show1 s = new Show1();
		s.show("show");
		s.print(new Integer(5));
		s.print("print");
	}
}

//15-10
package com.eclipsedemo;

interface Inter<T>{
	void show(T t);
}

class InterImpl implements Inter<String>{
	public void show(String t){
		System.out.println("show: " + t);
	}
}

class InterImpl1<T> implements Inter<T>{
	public void show(T t){
		System.out.println("show: " + t);
	}

}

class  Demo
{
	public static void main(String[] args) 
	{
		InterImpl1<Integer> i1 = new InterImpl1<Integer>();
		i1.show(4);
		
		InterImpl i = new InterImpl();
		i.show("F");
	}
}


package com.eclipsedemo;

/*15-12
?通配符,也叫占位符。 <T>与?的区别,?不能当参数传递。T相当于是形参,?相当于是实参。
泛型限定:
? extends E: 可以接收E类型或者E的子类型。--上限。  
? super E: 可以接收E类型或者E的父类型。--下限。

 */

import java.util.ArrayList;
import java.util.Iterator;

class  Demo
{
	public static void main(String[] args) 
	{
		Student s = new Student("std");
		System.out.println(s.getName());//为何这里返回的是存在 子类对象中的父类对象内的name呢?
/*		ArrayList<String> al = new ArrayList<String>();
		al.add("string1");
		al.add("string2");
		al.add("string3");
		
		ArrayList<Integer> al1 = new ArrayList<Integer>();
		al1.add(1);
		al1.add(2);
		al1.add(3);
		
//		printColl(al);
//		printColl(al1);
		
//		ArrayList<? extends Person> al3 = new <? extends Person>();
		ArrayList<Person> al2 = new ArrayList<Student>();//此处不可行的原因是左边明确可以放
		Person类型,即Worker也可以放,但是右边却声明只能放Student不能放Worker,所有会矛盾。

		ArrayList<Person> al2 = new ArrayList<Person>();
		ArrayList<Student> al3 = new ArrayList<Student>();
		//泛型必须保持左右两边一致,因为多态的情况在编译时就可以检测父类中是否有子类的方法
		//这样当父类调用了子类特有的方法是就会在编译时报错,
		//但泛型在编译时并没有明确左边的类型,因此无法在编译时检测是否有调用子类特有的方法
		//使用泛型必须保证左右两边一致,以便于在编译时检测出错误。
		
		
		al2.add(new Person("person 1"));
		al2.add(new Person("person 2"));
		al2.add(new Person("person 3"));
		
		al3.add(new Student("student 1"));
		al3.add(new Student("student 2"));
		al3.add(new Student("student 3"));
		
		printColl1(al2);
		printColl1(al3);*/
	}
	
	public static void printColl1(ArrayList<? extends Person> a){
		Iterator <? extends Person> it = a.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
			//System.out.println(it.next().toString());//可以使用toString(), 因为是所有对象都具备的方法。
			//System.out.println(it.next().length()); 不可以使用具体类型的方法。
		}
	}
	
	//public static void printColl(ArrayList<String> a){//此时不可以传入ArrayList<Integer>,
	//ArrayList<String> = new ArrayList <Integer>();因为必须保持左右两边类型一致.
/*	public static void printColl(ArrayList<?> a){
		Iterator <?> it = a.iterator();
		while(it.hasNext()){
			System.out.println(it.next().toString());//可以使用toString(), 因为是所有对象都具备的方法。
			//System.out.println(it.next().toString());如果在该迭代器中没有元素,却还在调用next();方法,就会发生NoSuchElement异常。
			//System.out.println(it.next().length()); 不可以使用具体类型的方法。因为?型没有该方法。
		}
	}*/

/*	public static <T>void printColl1(ArrayList<T> a){//<T>与?的区别,?不能当参数传递。T相当于是形参,?相当于是实参。
		//T是指一个具体类型,?是指不明确什么类型。
		Iterator <T> it = a.iterator();
		while(it.hasNext()){
			T t = it.next();
			System.out.println(t);
		}
	}*/
}

class Person{
	private String name;

	public Person(String string) {
		// TODO Auto-generated constructor stub
		//System.out.println(string);
		name = string;
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return name;
	}
	
	public String getName(){
		return name;
	}
	
}

class Student extends Person{
	
	private String name;
	public Student(String string) {
		super(string);
		System.out.println(name);
		this.name = "子类的name";
		// TODO Auto-generated constructor stub
	}//Person 的 name 是private,子类并没有继承, 那么 子类在调用 toString() 方法时,
	//子类的name 是 存在哪里呢? 验证得到结果是存储在 子类对象的 中的 父类对象 内,即使父类中的private 变量子类不可见,但仍然可以通过父类的方法来调用。
	//这样,即使在子类中并未声明 name 变量,也可以把自己需要的数据 隐藏在 父类对象中。
	
	public void show(){
		System.out.println("name = " + super.getName());
	}
	
}


import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

/*15-13
问题
?extends E
? super E
1.这两种模式分别在什么时候用?
2.eclipse 出现的问题
3.comparator 为什么不用覆盖 equals方法?*/
public class Demo {

	public static void main(String[] args){
		//TreeSet<Student> ts = new TreeSet<Student>(new PComp());
		
		//传入的是PComp 就不用再写 Comp 和 WorkerComp
		TreeSet<Student> ts = new TreeSet<Student>(new PComp());
		ts.add(new Student("abc013"));
		ts.add(new Student("abc05"));
		ts.add(new Student("abc01"));
		
		Iterator<Student> it = ts.iterator();
		
		while(it.hasNext()){
			System.out.println(it.next().getName());
		}
		
		TreeSet<Worker> wts = new TreeSet<Worker>(new PComp());
		wts.add(new Worker("w-ab-015"));
		wts.add(new Worker("w-ab-05"));
		wts.add(new Worker("w-ab-01"));
		
		Iterator<Worker> wit = wts.iterator();
		
		while(wit.hasNext()){
			System.out.println(wit.next().getName());
		}
		
	}
}

class Person{
	private String name;
	Person(String name){
		this.name = name;
	}
	
	public String getName(){
		return name;
	}
	
	public String toString(){
		return "person: " + name;
	}
}

class Student extends Person{

	Student(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}
	
}

class Worker extends Person{

	Worker(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}
	
}

class Comp implements Comparator<Student>{
	public int compare(Student s1, Student s2){
		return s1.getName().compareTo(s2.getName());
	}
}

class WorkerComp implements Comparator<Worker>{
	public int compare(Worker s1, Worker s2){
		return s1.getName().compareTo(s2.getName());
	}
}

class PComp implements Comparator<Person>{
	public int compare(Person s1, Person s2){
		return s1.getName().compareTo(s2.getName());
	}
}


---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ---------------------- 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值