泛型

  • JDK1.5出现的安全机制
  • 将运行时期的问题ClassCastException转到了编译时期
  • 避免了强制转换的麻烦
  1. 当操作的引用数据类型不确定的时候,就使用泛型,将要操作的数据类型传入即可
  2. 在程序中遇到了<>,就必须传入数据类型
  3. 泛型是给编译器使用的,保证编译
  4. 运行时会把泛型去掉,字节码中没有泛型,这个称为泛型的擦除,因为为了兼容运行时的类加载器
  5. 泛型的补偿:运行时通过获取元素的类型进行转换,不用使用者再强制转换了

集合的泛型

//main
//TreeSet<Person> ts = new TreeSet<Person>();
TreeSet<Person> ts = new TreeSet<Person>(new ComparatorByName());
ts.add(new Person("zhangsan",28));
ts.add(new Person("zhangsan1",26));
ts.add(new Person("zhangsan2",22));
ts.add(new Person("zhangsan3",35));
ts.add(new Person("zhangsan3",28));


Iterator<Person> it = ts.iterator();
while(it.hasNext()) {
    Person p = it.next();
    System.out.println(p.getName()+"--"+p.getAge());
}
//Person
public class Person extends Object implements Comparable<Person> {
	private String name;
	private int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public int compareTo(Person p) {
		int temp = this.age-p.age;
		return temp==0?this.name.compareTo(p.name):temp;
	}
}
//ComparatorByName
public class ComparatorByName implements Comparator<Person> {
	@Override
	public int compare(Person p1, Person p2) {

		int temp = p1.getName().compareTo(p2.getName());
		
		return temp==0?p1.getAge()-p2.getAge() : temp;
	}
}

泛型类

//Tool
public class Tool<T> {

	private T t;
	public T getObject() {
		return this.t;
	}
	public void setObject(T t) {
		this.t = t;
	}
	/**
	 * 泛型方法:可以方法上自定义泛型,这样就可以随便传值
	 * @param w
	 */
	public <W> void show(W w) {
		System.out.println("show..."+w);
	}
	public void print(T t) {
		System.out.println("Print..."+t);
	}
	/**
	 * 静态方法:静态方法要使用泛型就要在方法上定义泛型来使用
	 * @param w
	 */
	public static <S> void method(S s) {
		System.out.println("Static..."+s);
	}
}
//Main
Tool<String> tl = new Tool<String>();
tl.show(123);
tl.print("234");
Tool.method(465);

泛型接口

//接口
public interface Inter<T> {
	public void show(T t);
}
//实现
// 在实现的时候就传入数据类型
public class InterImp implements Inter<String> {
	@Override
	public void show(String t) {
		System.out.println(t);
	}
}
//main
InterImp inter = new InterImp();
inter.show("123");


//实例化的时候才传入数据类型
public class InterImp<Q> implements Inter<Q> {
	@Override
	public void show(Q q) {
		System.out.println(q);
	}
}
//main
InterImp<String> inter = new InterImp<String>();
inter.show("234");
public class TestGeneric {
	public static void main(String[] args) {
		
		InterImp<String> imp = new InterImp<String>();  //实例化的时候传入类型
		Son<String> son = new Son<String>();  //实例化的时候传入类型
		
		son.show("123");  //和实例化传入的类型一样
		son.method(123); //自定义类型方法
		son.method("123");
		son.aMethod(456);
		son.aMethod("123","456","789");  //自定义可变参数类型方法
	}
}
class Fu<T>{
	
}
interface Inter<T>{
	
}
//class Son extends Fu<String>{
//	
//}  定义的时候传入类型
//class InterImp implements Inter<String>{
//	
//}  定义的时候传入类型
class InterImp<Q> implements Inter<Q> {
}
class Son<T> extends Fu<T>{
	
	public void show(T t) {
		System.out.println(t);
	}
	
	public <Q> void method(Q q) {
		System.out.println(q);
	}
	
	public <K> void aMethod(K...k) {
		System.out.println(k);
	}
}

通配符 ?

//main
ArrayList<String> al1 = new ArrayList<String>();
al1.add("al11");
al1.add("al12");
al1.add("al13");

ArrayList<String> al2 = new ArrayList<String>();
al2.add("al21");
al2.add("al22");
al2.add("al23");

ArrayList<Integer> al3 = new ArrayList<Integer>();
al3.add(1);
al3.add(2);
al3.add(3);

printCollection(al1);
printCollection(al2);
printCollection(al3);

private static void printCollection(Collection<?> al) {
	Iterator<?> it = al.iterator();
	while(it.hasNext()) {
//    		String s = it.next();
		System.out.println(it.next());
	}
}

// ? extends E 接收E类型或E的子类型 上限! //? super E 接收E类型或E的父类型 下限!

//main
ArrayList<Student> als = new ArrayList<Student>();
als.add(new Student("s1",21));
als.add(new Student("s2",22));
als.add(new Student("s3",23));

ArrayList<Worker> alw = new ArrayList<Worker>();
alw.add(new Worker("w1",24));
alw.add(new Worker("w2",25));
alw.add(new Worker("w3",26));

printCollection(als);
printCollection(alw);

ArrayList<Person> alp = new ArrayList<Person>();
alp.add(new Worker("p1",27));
alp.add(new Worker("p2",28));
alp.add(new Worker("p3",29));

printCollectionBySuper(alp);

private static void printCollection(Collection<? extends Person> al) {
	Iterator<? extends Person> it = al.iterator();
	while(it.hasNext()) {
		Person s = it.next();
		System.out.println(s);
	}
}
private static void printCollectionBySuper(Collection<? super Student> al) {
	Iterator<? super Student> it = al.iterator();
	while(it.hasNext()) {
		System.out.println(it.next());
	}
}

一般存储元素的时候都是用上限,因为这样取出都是按上限类型来运算,不会出现安全隐患 比如addAll addAll(? extends E)

一般取出元素的时候都是用下限

containAll(Collection<?>) 这个也是通配符,里面都是Object,不确定类型

特点

  • 需要唯一? 需要:Set

    • 需要顺序? 需要:TreeSet 不需要:HashSet 有序:LinkedHashSet 不需要:List
      • 需要频繁增删? 需要:LinkedList 不需要:ArrayList
  • List ArrayList LinkedList

  • Set HashSet TreeSet

  1. 后缀名就是集合所属的体系
  2. 前缀名就是集合的数据结构
    • array:数组,查询快,有角标
    • link:链表,增删快,add,get,remove+first/last方法
    • hash:哈希表,唯一性,元素需要覆盖hashCode和equals方法
    • tree:二叉树,排序,两个接口Comparable,Comoparator

常用容器都是不同步的


书籍推荐