黑马程序员——学习日记之泛型和集合框架工具类

                                                                    ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

第一节:泛型
一、泛型的由来和基本使用
1、因为集合可以存储的对象类型是任意的,在取出进行向下转型时,容易发生ClassCastException。
所以JDK1.5以后就有了解决这个问题的技术:泛型。
2、泛型的原理:其实就是在操作的元素类型不确定时,通过传递参数的形式来明确类型。
3、泛型的体现就是 <参数类型变量>用于接收具体的实际元素类型。
4、泛型技术在集合框架中应用非常广泛,只要记住:在使用类或者接口时,如果接口上有明确<>泛型。
在使用时,就传递所需的数据类型即可。不传递会出现警告类型不安全提示。
5、了解:泛型技术是用在编译器部分的技术,一旦类型检查正确,
生成的class文件中就没有泛型标记了:这是的泛型的擦除。
6、泛型的好处:
6.1 将运行时期的ClassCastException异常转移到编译时期通过编译失败体现。
6.2 避免了强制转换的麻烦。
7、其实泛型的使用就是往定义了泛型的类或者接口的<>中传递类型参数。
8、泛型在集合对象中的使用,要求写集合代码时必须加入泛型 
代码体现

[java]  view plain copy
  1. import java.util.*;  
  2. class FanXingDemo  
  3. {  
  4.     public static void main(String[] args)  
  5.     {     
  6.         List<String> list = new ArrayList<String>();  
  7.         //添加元素  
  8.         list.add("abc");  
  9.         list.add("zzzz");  
  10. //      list.add(6);//只要不是指定的类型对象,编译器检查会 报错。这样将运行时的问题转移到编译时期。  
  11.         //用迭代器进行对元素遍历  
  12.         for (Iterator<String> it = list.iterator(); it.hasNext();)   
  13.         {  
  14. //          Object object = (Object) it.next();  
  15. //          System.out.println(object.toString());  
  16.             //想要打印字符串的长度。  
  17.             String str = it.next();  
  18.             System.out.println(str.length());     
  19.         }  
  20.     }  
  21. }  

二、自定义泛型
1、没有泛型之前,对于不确定的对象类型,是通过Object类型多态方式解决的。
弊端:当对象提升为Object后,需要向下转型才可以使用对象的内容。
而转型就会有运行发生ClassCastException异常的风险。
2、有了泛型后,将不确定的类型定义成参数,把Object替换成参数类型。
好处是:调用者在使用时必须先明确类型,如果操作的对象类型不符符合,直接编译失败。
类型符合,使用对象特有方法时,不需要进行强制转换。
3、泛型类,泛型方法,泛型接口的体现
(3) 泛型类
(3).1 把泛型定义在类上 格式:public class 类名<泛型类型1,…>
   注意:泛型类型必须是引用类型
(3) 泛型方法
把泛型定义在方法上 格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
(3) 泛型接口
把泛型定义在接口上 格式:public  interface 接口名<泛型类型1…>
4、注意:
4.1 类上的泛型是在创建该类对象时进行类型明确。
4.2 静态方法无法访问类上定义的泛型,如果需要泛型,只能定义在方法上。

       代码体现

[java]  view plain copy
  1. import java.util.*;  
  2. class Queue<E>{  
  3.     //封装了一个LinkedList类。  
  4.     private LinkedList<E> link;  
  5.     //类初始化,LinkedList对象初始化。  
  6.     Queue(){  
  7.         link = new LinkedList<E>();  
  8.     }  
  9.     public void myAdd(E obj){  
  10.         //添加元素  
  11.         link.addFirst(obj);  
  12.     }  
  13.      // 队列的获取方法。  
  14.     public E myGet(){  
  15.         return link.removeLast();  
  16.     }  
  17.     // 判断队列中元素是否空  
  18.     public boolean isNull(){  
  19.         return link.isEmpty();  
  20.     }  
  21. }  

三、通配符和泛型的限定
    1、当使用了带有泛型的类时,需要传递具体类型实参时,无法明确要传递的实参,可以用?通配符表示。
2、如果要操作的对象的类型是在一个范围之内,比如只操作Person或者Person的子类型对象时。
这时可以使用泛型的限定,对要操作的类型进行限制,提高程序类型操作的安全性。
3、泛型限定体现:
? extends E :接受E类型或者E的子类型。上限。

          代码体现

[java]  view plain copy
  1. import java.util.*;  
  2. class FanXingDemo5  
  3. {  
  4.     public static void main (String[] args)  
  5.     {  
  6.         //创建list对象,并添加元素  
  7.         List<Student>s =new ArrayList<Student>();  
  8.         s.add(new Student("张三"));  
  9.         s.add(new Student("小三"));  
  10.         s.add(new Student("小五"));  
  11.         s.add(new Student("小六"));  
  12.         getStudent(s);  
  13.         //创建list对象,并添加元素  
  14.         List<Wroker>s1 =new ArrayList<Wroker>();  
  15.         s1.add(new Wroker("李四"));  
  16.         s1.add(new Wroker("小四"));  
  17.         s1.add(new Wroker("小李"));  
  18.         getStudent(s1);  
  19.     }  
  20.     //对传入的对象进行限定  
  21.     public static void getStudent(Collection<?extends Person> cl)  
  22.     {  
  23.         //进行迭代  
  24.         for(Iterator<?extends Person> iee = cl.iterator();iee.hasNext();)  
  25.         {  
  26.                     //打印出集合中的元素  
  27.             System.out.println(iee.next());  
  28.         }  
  29.     }  
  30. }  
  31. //人类  
  32. class Person  
  33. {  
  34.     private String name;  
  35.     Person(String name)  
  36.     {  
  37.         this.name=name;  
  38.     }  
  39.     public String getName()  
  40.     {  
  41.     return name;  
  42.     }  
  43.     public String toString()  
  44.     {  
  45.     return name;  
  46.     }  
  47. }  
  48. //工人继承了人类  
  49. class Wroker extends Person  
  50. {  
  51.     Wroker(String name)  
  52.     {  
  53.         super(name);  
  54.     }  
  55. }  
  56. //学生继承了人类  
  57. class Student extends Person  
  58. {  
  59.     Student(String name)  
  60.     {  
  61.         super(name);  
  62.     }  
  63. }  

? super E   :接受E类型或者E的父类型。下限。

[java]  view plain copy
  1. import java.util.*;  
  2. class FanXingDemo5  
  3. {  
  4.     public static void main (String[] args)  
  5.     {  
  6.         //创建list对象,并添加元素  
  7.         Set<Student>s =new TreeSet<Student>(new myComparator());  
  8.         s.add(new Student("张三",23));  
  9.         s.add(new Student("小三",32));  
  10.         s.add(new Student("小五",54));  
  11.         s.add(new Student("小六",12));  
  12.         getStudent(s);  
  13.         //创建list对象,并添加元素  
  14.         Set<Wroker>s1 =new TreeSet<Wroker>(new myComparator());  
  15.         s1.add(new Wroker("李四",36));  
  16.         s1.add(new Wroker("小四",87));  
  17.         s1.add(new Wroker("小李",43));  
  18.         getStudent(s1);  
  19.     }  
  20.     //对传入的对象进行限定  
  21.     public static void getStudent(Collection<?extends Person> cl)  
  22.     {  
  23.         //进行迭代  
  24.         for(Iterator<?extends Person> iee = cl.iterator();iee.hasNext();)  
  25.         {  
  26.                     //打印出集合中的元素  
  27.             System.out.println(iee.next());  
  28.         }  
  29.     }  
  30. }  
  31. //人类  
  32. class Person  
  33. {  
  34.     private String name;  
  35.     private int age;  
  36.     Person(String name,int age)  
  37.     {  
  38.         this.name=name;  
  39.         this.age=age;  
  40.     }  
  41.     public String getName()  
  42.     {  
  43.     return name;  
  44.     }  
  45.     public int getAge()  
  46.     {  
  47.     return age;  
  48.     }  
  49.     public String toString()  
  50.     {  
  51.     return name;  
  52.     }  
  53. }  
  54. //工人继承了人类  
  55. class Wroker extends Person  
  56. {  
  57.     Wroker(String name,int age)  
  58.     {  
  59.         super(name,age);  
  60.     }  
  61. }  
  62. //学生继承了人类  
  63. class Student extends Person  
  64. {  
  65.     Student(String name,int age)  
  66.     {  
  67.         super(name,age);  
  68.     }  
  69. }  
  70. //定义一个比较器  
  71. class myComparator implements Comparator<Person>//泛型内的元素定义成Person类,所以wroker类和Student都可以用  
  72. {  
  73.     public int compare(Person s1,Person s2)  
  74.     {  
  75.         int temp =s1.getName().compareTo(s2.getName());  
  76.         return temp==0?s1.getAge()-s2.getAge():temp;  
  77.     }  
  78. }  
4、在api中的体现
(1) 通配符的api体现:
Collection中的containsAll(Collection<?> c):因为该方法内部使用的是equals方法,
而equals(Object)方法是可以和任意对象进行比较,所以传递进来的集合元素是什么类型都可以,
无法确定具体的类型参数用?表示。
(2) 上下限api的体现。TreeSet集合的构造函数。
TreeSet(Collection<? extends E> c) :在给TreeSet集合初始化元素时,
传递进来的容器中的元素类型只要时TreeSet集合明确的类型或者子类型都可以。
TreeSet(Comparator<? super E> comparator) :在明确TreeSet比较器时,
只要是TreeSet集合元素类型的比较器,或者该元素类型的父类型都接收元素对象进行比较。

5、泛型限定的练习。

代码体现

[java]  view plain copy
  1. //泛型的练习  
  2. /* 
  3.          * 案例:获取集合中元素的最大值。 
  4.          *  
  5.          * 思路: 1,定义变量记录每次比较后较大的值,初始化元素中任意一个。 2,遍历容器 
  6.          * 3,在遍历中和变量中记录的元素进行比较。并将较大的值记录到变量中。 4,遍历结束,变量中记录的就是最大值。 
  7.          */  
  8. import java.util.*;  
  9. class FanXingDemo4  
  10. {  
  11.     public static void main (String[] args)  
  12.     {  
  13.     //不加泛型进行获取  
  14.     Set<Student> s1 =new TreeSet<Student>();  
  15.     s1.add(new Student("王五",39));  
  16.     s1.add(new Student("小五",19));  
  17.     s1.add(new Student("大五",99));  
  18.     Student max=getValue(s1);  
  19.     System.out.println(max);  
  20.     }  
  21.   
  22.     // 升级版。要操作的元素的类型确定不?不确定。使用泛型限定。getMax方法接收的集合中的元素无论时什么类型,必须具备自然排序,必须是Comparable的子类。  
  23.     public static <T extends Comparable<?super T>> T getValue(Set<?extends T> cle)  
  24.     {  
  25.         Iterator<?extends T> ies = cle.iterator();  
  26.         T max =ies.next();  
  27.         while (ies.hasNext())  
  28.         {  
  29.             T temp=ies.next();  
  30.             if (temp.compareTo(max)>0)  
  31.             {  
  32.                 max=temp;  
  33.             }  
  34.         }  
  35.     return max;  
  36.     }  
  37. }  
  38.   
  39. //自定义一个学生类并实现了Comparable接口  
  40. class Student implements Comparable<Student>  
  41. {  
  42.     //私有学生类的属性  
  43.     private String name;  
  44.     private int age;  
  45.     Student(String name,int age)  
  46.     {  
  47.         this.name=name;  
  48.         this.age=age;  
  49.     }  
  50.         //并提供对外访问方式  
  51.     public String getName()  
  52.     {  
  53.       
  54.     return name;  
  55.     }  
  56.     public int getAge()  
  57.     {  
  58.         return age;  
  59.     }  
  60.     //覆盖接口中的CompareTo方法  
  61.     public int compareTo(Student stu)  
  62.     {  
  63.         //看看name是否相同  
  64.         int temp=this.name.compareTo(stu.name);  
  65.         //当name和age相同时为同一个人  
  66.         return temp==0?this.age-stu.age:temp;  
  67.     }  
  68.     //覆盖Object中的toString方法  
  69.     public String toString()  
  70.     {  
  71.     return "name="+name+".....age="+age;  
  72.     }  
  73. }  
第二节: 集合框架的工具类
一、简述:
1、Collections和Arrays :是集合框架的工具类。里面定义的都是静态方法。
2、Collections工具类中基本上的方法都是对于对List集合进行操作的,例如查找、排序、获取最大值 最小值等方法。
3、Arrays:针对数组进行操作的工具类。提供了排序,查找等功能。
二、Collections 的常见方法
1、排序
public static <T> void sort(List<T> list)根据自然顺序对list集合中的元素进行排序
public static void shuffle(List<?> list)使用默认随机源对list集合中的元素进行随机排序
2、查找
public static <T> int binarySearch(List<?> list,T key)二分法搜索list集合中的指定对象
public static <T> T max(Collection<?> coll)根据集合的自然顺序,获取coll集合中的最大元素。
3、反转
public static void reverse(List<?> list)把list集合中元素的顺序进行反转。
三、Collections和Collection的区别
1、Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法,它有两个常用的子接口:List  Set。
2、Collections:集合框架的工具类,里面定义的都是静态方法。基本上都是对于对List集合进行操作的,例如查找、排序、获取最大值 最小值等方法,
也可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
四、Arrays 的常见方法
1、public static String toString(int[] a)把一个数组转变成字符串。
        2、public static void sort(int[] a)把数组里面的元素进行排序。
        3、public static int binarySearch(int[] a,int key)二分查找。
五、集合与数组之间相互转换
1、public static Lsit<T> asList(T... a)将数组转换为集合
(1)、当把一个数组转变成一个集合时,不能使用集合中的增删方法,那是由于数组的长度是固定不变的,要是用的法,在编译时期报出UnsupportedOperationException异常。
(2)、当数组转变成集合的时候,假如数组元素是对象的话,数组中的元素就成了集合中的元素了,要是基本数据类型,这个数组就成了集合中的元素了。
2、Collection接口中的toArray方法  集合转变成数组
(1)、好处:可以对集合中的元素操作的方法进行限定,但不允许对其进行增删。 
(2)、在toArray方法中需要传入一个指定类型的数组,既然是数组那么它的长度该如何定义呢?
(2).1 如果长度小于集合的size,那么该方法会创建一个同类型并和集合相同size的数组。
(2).2 如果长度大于集合的size,那么该方法就会使用指定的数组,存储集合中的元素,其他位置默认为null。
(2).3 如果长度等于集合的size, 在最好不过了。
第三节:1.5版本的新特性
一、高级for循环
1、是for循环的一种
2、格式:
for(元素的数据类型 变量名 : 数组或者Collection集合的对象) {
使用该变量即可,该变量其实就是数组或者集合中的元素。
}
3、好处:
简化了数组和集合的遍历
4、弊端:
高级for循环的目标不能为null。建议在使用前,先判断是否为null。
5、传统for和高级for的区别? 
(1)、传统for可以完成对语句执行很多次,因为可以定义控制循环的增量和条件。      
(2)高级for是一种简化形式。 
   (2).1 它必须有被遍历的目标。该目标要是数组,要么是Collection单列集合。      
   (2).2 对数数组的遍历如果仅仅是获取数组中的元素,可以使用高级for。 
   (2).3 如果要对数组的角标进行操作建议使用传统for。 
6、代码体现

[java]  view plain copy
  1. class Demo16  
  2. {  
  3.     public static void main(String[] args)  
  4.     {  
  5.     //传统for遍历数组  
  6.         int[] array= {1,2,3};  
  7.   
  8.         for(int x=0; x<array.length; x++)  
  9.         {  
  10.             System.out.println(array[x]);  
  11.         }  
  12.         //高级for遍历数组  
  13.         for(int in : array)  
  14.         {  
  15.             System.out.println("in:"+in);  
  16.         }  
  17.     }   
  18. }  
二、函数的可变参数
1、如果我们在写方法的时候,参数个数不明确,就应该定义可变参数,其实就是一个数组,但是接收的是数组的元素,自动将这些元素封装成数组。简化了调用者的书写。
2、格式:
修饰符 返回值类型 方法名(数据类型... 变量) {}
注意:
(1)、该变量其实是一个数组名。
(2)、如果一个方法有多个参数,并且有可变参数,可变参数必须在最后。
3、Arrays工具类的一个方法
asList()把数组转成集合。
4、代码体现

[java]  view plain copy
  1. class  Demo17  
  2. {  
  3.     public static void main(String[] args)   
  4.     {  
  5.         //传入一定量的数  
  6.         show(1,2,3,4,5,6);  
  7.     }  
  8.     public static void show(int... array)//...就表示可变参数  
  9.     {  
  10.         //打印array的长度  
  11.         System.out.println(array.length);  
  12.     }  
  13. }  
三、静态导入
1、可以导入到方法级别的导入
2、格式:
import static 包名....类名.方法名。
3、注意事项:
(1)、方法必须是静态的。
(2)、如果多个类下有同名的方法,就不好区分了,还得加上前缀。
所以一般我们并不使用静态导入,但是一定要能够知道看懂。
4、代码体现
[java]  view plain copy
  1. import static java.util.Arrays.*;  
  2. import static java.lang.System.*;  
  3.   
  4. class  Demo18  
  5. {  
  6.     public static void main(String[] args)   
  7.     {  
  8.         int[] arr = {2,1,9,8};  
  9.   
  10.         sort(arr);//方法sort时就可以省略书写Array.  
  11.   
  12.         for (int x=0;x<arr.length ;x++ )  
  13.         {  
  14.             out.println(arr[x]);//打印可以省略System  
  15.         }  
  16.     }  
  17. }  

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值