1、泛型
升级三特性:高效、安全、简化书写。
泛型是JDK1.5版本以后出现的新特性,用于解决安全问题,是一个安全机制。
泛型好处:第一、将运行时期出现的问题ClassCastException,转移到了编译时期,方便程序员解决问题,让运行时问题减少,提高安全性。第二、避免强制转换麻烦。
2、泛型格式
泛型格式:通过<>来定义要操作的引用数据类型。
在使用java提供的对象时,什么时候用泛型呢?通常在集合框架中很常见,只要看见<>就要定义泛型。其实<>就是用来接收类型的。当使用集合时,将集合中要存储的数据类型作为参数传到<>中即可。Object类没有泛型。
3、泛型类
什么时候定义泛型类?当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展,现在定义泛型来完成扩展。
4、泛型方法
泛型类缺点:泛型方法会随泛型类!泛型类定义的泛型,在整个类中有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法操作不同类型,而且类型还不确定,就可以将泛型定义在方法上。
//泛型类缺点
class Demo<T>{
public void show(T t){
System.out.println("show:"+t);
}
public void print(T t){
System.out.println("print:"+t);
}
}
//泛型方法优点
class Demo{
public <T> void show(T t){
System.out.println("show:"+t);
}
public <Q> void print(Q q){
System.out.println("show:"+q);
}
}
5、静态方法泛型
特殊之处:静态方法不可以访问类上定义的泛型,如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。
6、泛型接口
泛型接口和泛型类差不多定义,
interface Inter<T>{
void show(T t);
}
7、泛型通配符
也可以理解为占位符:<?>。当类型不确定时,用通配符替代具体的类型。
加了泛型就没具体的类型,要使用泛型就要强转成用的类型。
8、泛型限定
上限:<? extends E>,E为父类,?为子类。可以使用E 或者 E的子类。
下限:<? super E>,E为子类,?为父类。可以使用E 或者 E的父类。
import java.util.*;
class Person{
private String name;
Person(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public String toString(){
return "person:"+name;
}
}
class Student extends Person{
Student(String name){
super(name);
}
}
class Worker extends Person{
Worker(String name){
super(name);
}
}
/*
上限:<? extends E>,E为父类,?为子类。可以使用E 或者 E的子类。
下限:<? super E>,E为子类,?为父类。可以使用E 或者 E的父类。
*/
/*
class MyComparator implements Comparator<Student>{
public int compare(Student stu1,Student stu2){
return stu1.getName().compareTo(stu2.getName());
}
}
class MyComparator2 implements Comparator<Worker>{
public int compare(Worker stu1,Worker stu2){
return stu1.getName().compareTo(stu2.getName());
}
}*/
class MyComparator3 implements Comparator<Person>{
public int compare(Person stu1,Person stu2){
return stu1.getName().compareTo(stu2.getName());
}
}
public class GenericDemo07{
public static void main(String[] args){
TreeSet<Student> ts = new TreeSet<Student>(new MyComparator3());
ts.add(new Student("abc003---student"));
ts.add(new Student("abc004---student"));
ts.add(new Student("abc001---student"));
ts.add(new Student("abc06---student"));
Iterator<Student> it = ts.iterator();
while(it.hasNext()){
System.out.println(it.next().getName());
}
TreeSet<Worker> ts2 = new TreeSet<Worker>(new MyComparator3());
ts2.add(new Worker("abc003---***WORKER"));
ts2.add(new Worker("abc004---***WORKER"));
ts2.add(new Worker("abc001---***WORKER"));
ts2.add(new Worker("abc06---***WORKER"));
Iterator<Worker> it2 = ts2.iterator();
while(it2.hasNext()){
System.out.println(it2.next().getName());
}
}
}
9、Map<K,V>集合:该集合存储键值对。一对一往里存,而且要保证键的唯一性。
第一、添加
V put(K?key,V?value):put返回原来的值。添加元素,添加相同的键,那么后添加的值会覆盖原有键对应值,且put方法会返回原有的值。
void putAll(Map<? extends K,? extends V>?m)
第二、删除
void clear()
V remove(Object?key)
第三、判断
boolean containsKey(Object?key)
boolean containsValue(Object?value)
boolean isEmpty()
第四、获取
V get(Object?key)
int size()
Collection<V> values()
Set<Map.Entry<K,V>> entrySet()
Set<K> keySet()
10、Map集合层
Map
|---Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是同步的。JDK1.0效率低。
|---HashMap:底层是哈希表数据结构,可以存入null键null值。该集合是不同步的。JDK1.2效率高。除了这2点相同外,其余HashMap和HashMap差不多。
|---TreeMap:底层是二叉树数据结构。线程不同步。可以用于给Map集合中的键进行排序。
Map和Set很像,其实Set底层就是使用了Map集合。
11、map集合的两种取出方法
第一种、Set<K> keySet:将Map中所有的键存入到Set集合中,因为Set集合具备迭代器。所以可以利用迭代方式取出所有的键,再根据get方法获取每一个键对应的值。
Map集合的取出原理:将Map集合转成Set集合,再通过迭代器取出。
第二种、Set<Map.Entry<k,v>> entrySet:将Map集合中的映射关系存入到Set集合中,这个关系的数据类型就是Map.Entry。
import java.util.*;
public class MapDemo02{
public static void main(String[] args){
Map<String,String> map = new HashMap<String,String>();
map.put("02","zhangsan02");
map.put("03","zhangsan03");
map.put("01","zhangsan01");
map.put("04","zhangsan04");
//第一步、先将Map集合中所有的键取出,存入到的Set集合,使用的方法是keySet();
Set<String> keySet = map.keySet();
//第二步、有了Set集合,就可以获取Set集合迭代器;
Iterator<String> it = keySet.iterator();
while(it.hasNext()){
String key = it.next();
//第三步、有了键就可以通过Map集合的get方法获取其对应的值。
String value = map.get(key);
sop("key:"+key+",value:"+value);
}
//第一步、先将Map集合中的映射关系取出,存入到set集合中,使用的方法是entrySet();
//Map.Entry<String,String>是一种数据类型,保存的是键和值得关系;
Set<Map.Entry<String,String>> entrySet = map.entrySet();
//第二步、利用Set迭代器,将Set集合中映射关系取出;
Iterator<Map.Entry<String,String>> it = entrySet.iterator();
//第三步、利用Map.Entry接口自身的方法将键和值从映射关系中取出。
while(it.hasNext()){
Map.Entry<String,String> me= it.next();
sop(me.getKey()+":"+me.getValue());
}
}
public static void sop(Object obj){
System.out.println(obj);
}
}
12、Map.Entry<K,V>接口
Entry也是一个接口,他是Map接口中的一个内部接口。
interface Map{
public static interface Entry{
public abstract Object getKey();
public abstract Object getValue();
}
}
class HashMap implements Map{
class MapEntry implements Map.Entry{//内部类
public Object getKey(){…}
public Object getValue(){…}
}
}
13、Map扩展
映射关系可以为:一对多、集合的嵌套。
集合框架图
向上的实线为集合间的接口;
向上的虚线为集合间的实现类;