黑马程序员-----集合 泛型

来源:互联网 发布:listview 优化的原理 编辑:程序博客网 时间:2024/06/11 08:45

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

泛型

定义:泛型:jdk1.5版本以后出现新特性,用于解决安全问题,是一个类型安全机制

好处:

1,将运行时期出现问题classcastexception,转移到了编译时期,方便于程序员解决问题,让运行事情问题减少,安全。
2,避免了强制转换麻烦

格式:

通过<>来定义要操作的引用数据类型

在集合框架中,只要见到<>就要定义泛型,其实<>就是用来接收类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。

范例:


  1. public class GenericDemo3 {    
  2.     public static void main(String[] args) {    
  3.     Utils<Worker> u=new Utils<Worker>();    
  4.     u.setObject(new Worker());    
  5.     Worker w=u.getObject();    
  6.         /*Tool t=new Tool();  
  7.         t.setObject(new Worker());  
  8.         Worker w=(Worker)t.getObject();  
  9.         */    
  10.     }    
  11. }    
  12. class Worker    
  13. {    
  14. }    
  15. class Student3    
  16. {    
  17. }    
  18. //泛型前做法    
  19. //什么时候定义泛型类?    
  20. //当类中要操作的引用数据类型不确定的时候,早期定义object来完成扩展    
  21. //现在定义泛型来完成扩展    
  22. class Tool    
  23. {  private Object obj;    
  24.    public void setObject(Object obj)    
  25.    {    
  26.        this.obj=obj;    
  27.    }    
  28.    public Object getObject()    
  29.    {    
  30.        return obj;    
  31.    }    
  32. }    
  33. //泛型类。    
  34. class Utils<QQ>    
  35. {    
  36.     private QQ q;    
  37.     public void setObject(QQ q)    
  38.     {    
  39.         this.q=q;    
  40.     }    
  41.     public QQ getObject()    
  42.     {    
  43.         return q;    
  44.     }    
  45. }    
  46. /**  
  47. class Tool  
  48. {  private worker w;  
  49.    public void setWorker(worker w)  
  50.    {  
  51.        this.w=w;  
  52.    }  
  53.    public worker getWorker()  
  54.    {  
  55.        return w;  
  56.    }  
  57.  
  58. */    
泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型不确定,那么可以将泛型定义在方法上

 特殊之处:静态方法不可以访问类上定义的泛型,如果静态方法操作的 引用数据类型不确定,可以将泛型定义在方法上

泛型定在接口上的范例:


  1. public class genericDemo5 {    
  2.     /**  
  3.      * @param args  
  4.      */    
  5.     public static void main(String[] args) {    
  6.         // TODO Auto-generated method stub    
  7.    InterImpl<Integer> i=new InterImpl<Integer>();    
  8.         //  InterImpl i=new InterImpl();    
  9.       i.show(4);    
  10.     }    
  11. }    
  12. class InterImpl<T> implements Inter<T>//泛型定义在接口上    
  13. {    
  14.   public void show(T t)    
  15.   {    
  16.       System.out.println("show:"+t);    
  17.   }    
  18. }    
  19. /*class InterImpl implements Inter<String>  
  20. {public void show(String t)  
  21.  
  22.   System.out.println("show:"+t);      
  23.  
  24.  
  25. */    
  26. interface Inter<T>    
  27. {    
  28.     void show(T t);    
  29. }    
泛型也有限定,通配符?可以理解为占位符

 ? extends E :可以接受E类型或者E的子类型,上限
 ? super E:可以接受E类型或E的父类型,下限。

[java] view plaincopy
  1. import java.util.*;    
  2. class generademo6 {    
  3.     public static void main(String[] args)    
  4.     {    
  5.         /* ArrayList<String> a1=new ArrayList<String>();  
  6.          a1.add("abc1");  
  7.          a1.add("abc2");  
  8.          a1.add("abc3");  
  9.          ArrayList<Integer> a11=new ArrayList<Integer>();  
  10.          a11.add(4);//有自动装箱。  
  11.          a11.add(2);  
  12.          a11.add(5);  
  13.          printColl(a1);  
  14.          printColl(a11);*/    
  15.             ArrayList<Person> a1=new ArrayList<Person>();    
  16.         a1.add(new Person("abc1"));    
  17.         a1.add(new Person("abc2"));    
  18.         //printColl(a1);    
  19.         ArrayList<student11> a11=new ArrayList<student11>();    
  20.         a1.add(new student11("abc1"));    
  21.         a1.add(new student11("abc2"));    
  22.         printColl1(a11);//Arraylist<Person>a1=new Arraylist<Student>();是不允许的。error。两边一致    
  23.     }    
  24.     public static void printColl1(ArrayList<? extends Person/*泛型限定*/> a1)    
  25.     {    
  26.         Iterator<? extends Person> it=a1.iterator();    
  27.         while(it.hasNext())    
  28.         {    
  29.             System.out.println(it.next().getName());    
  30.         }    
  31.     }    
  32.  /*public static void printColl(ArrayList<?String>a1) //ArrayList<String>a1=new ArrayList<Integer>();不允许的。  
  33.   {  
  34.    Iterator<String? > it=a1.iterator();  
  35.    while(it.hasNext())  
  36.    {  
  37.        System.out.println(it.next());  
  38. //     System.out.println(it.next().length());//这不不能使用具体方法。  
  39.    }  
  40. }*/    
  41. }    
  42. class Person    
  43. {    
  44.    private String name;    
  45.   Person(String name)    
  46.   {    
  47.       this.name=name;    
  48.   }    
  49.   public String getName()    
  50.   {    
  51.       return name;    
  52.   }     
  53. }    
  54. class student11 extends Person    
  55. {    
  56.     student11(String name)    
  57.     {    
  58.         super(name);    
  59.     }    
  60. }    
  61. class student11 implements Comparable<Person>//<? super e>    
  62. {    
  63.     public int compareTo(Person s)    
  64.     {    
  65.         this.getName();    
  66.     }    
  67. }    
  68. class comp implements Comparator<Person>    
  69. {    
  70.   public int compare(Person s1,Person s2)    
  71.   {    
  72.       return s1.getName().compareTo(s2.getName());    
  73.   }    
  74. }    
  75. TreeSet<student11> ts=new TreeSet<student11>(new comp());    
  76. ts.add(new student11("abc11"));    
ClassCastException类型转换异常
Comparable 接口强行对实现它的每个类的对象进行整体排序,这种排序被称为自然排序。
Comparable只有comparableTo()
TreeSet内集合要具有比较性。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Map集合

Map
  |-----Hashtable此类实现一个哈希表,该哈希表将键映射到相应的值,任何非null对象都可以用作键或值。
  用作键的对象必须实现hashCode方法和equals方法。底层是哈希表数据结构,不可以存入null键null值,jdk1.0 效率低。该集合是线程同步的
  |-----HashMap:基于哈希表的map接口的实现,并允许使用null键,null值。底层是哈希表数据结构,jdk1.2 效率高。该集合是非同步的。
  |-----TreeMap:底层是二叉树数据结构,线程不同步,可以用于给map集合中的键进行排序


定义:public interface Map<K,V>将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值,collection单例集合,
Map集合:该集合存储键值对,一对一对往里存,而且保证键的唯一性。双列集合。

方法:

1,添加
  put(k key,v value)将指定的值与此映射中的指定键关联
  putAll(Map<? extends k,? extends v> m)从指定映射中将所有映射关系复制到此映射中
  2,删除
 void clear();从此映射中移除所有映射关系。即清空
 value remove(Object key);如果存在一个键的映射关系,则将其从此映射中移除,删除指定键
  3,判断
 boolean containsKey(object key);如果此映射包含指定键的映射关系,则返回true, 是否包含key.
 boolean containsValue(object value);如果此映射将一个或多个键映射到指定值,则返回true。是否包含value.
 boolean isEmpty();如果此映射未包含键值映射关系,则返回true。
  4,获取
value  get(Object key)返回指定键所映射的值,如果此映射不包含该键的映射关系,则返回null
int size();返回此映射中的键值映射关系数。
Collection values();返回此映射中包含的值的collection视图。获取map集合中的所有的值。
 entrySet();返回此映射中包含的映射关系的set视图。
keySet();返回此映射中包含的键的set视图。

5,想要获取map中的所有元素:
  原理:map中是没有迭代器的,collection具备迭代器,只要将map集合转成Set集合,可以使用迭代器了。之所以转成set,是因为map集合具备着键的唯一性,其实set集合就来自于map,set集合底层其实用的就是map的方法

Map集合存储和Collection的区别:
Collection一次存一个元素;Map一次存一对元素。
Collection是单列集合;Map是双列集合。
Map中的存储的一对元素:一个是键,一个是值,键与值之间有对应(映射)关系。


  1. import java.util.*;    
  2. public class MapDemo {    
  3. public static void main(String[] args) {    
  4.         Map<String,String>map=new HashMap<String,String>();    
  5.         //添加元素,添加元素如果出现添加时,相同的键,那么后添加的值会覆盖原有键对应值,并put    
  6.         //方法会返回被覆盖的值。    
  7.         map.put("01","zhangs");    
  8.         map.put("02""jav12");    
  9.         map.put("03","jv23");    
  10.                   System.out.print("cont"+map.containsKey("023"));    
  11.                   System.out.println("remove"+map.remove("02"));    
  12.                   System.out.println("get:"+map.get("023"));    
  13.                   map.put("04"null);    
  14.                   System.out.println("get:"+map.get("04"));    
  15.                   //可以通过get方法的返回值来判断一个键是否存在,通过返回null来判断    
  16.                      //获取map集合中所有的值    
  17.                      Collection<String> coll=map.values();    
  18.                   System.out.println(coll);    
  19.                   System.out.println(map);    
map集合的两种取出方式

取出map集合中所有元素的方式一:keySet()方法。
可以将map集合中的键都取出存放到set集合中。对set集合进行迭代。迭代完成,再通过get方法对获取到的键进行值的获取。


  1. Set keySet = map.keySet();  
  2.       Iterator it = keySet.iterator();  
  3.      while(it.hasNext()) {  
  4.          Object key = it.next();  
  5.          Object value = map.get(key);  
  6.          System.out.println(key+":"+value);  
  7.      }  
取出map集合中所有元素的方式二:entrySet()方法。

set<Map.Entry<k,v>>entryset:将map集合中的映射关系存入到了set集合中,而这个集合的数据类型就是:Map.Entry


  1. Set entrySet = map.entrySet();  
  2.         Iterator it = entrySet.iterator();  
  3.         while(it.hasNext()) {  
  4.             Map.Entry  me = (Map.Entry)it.next();  
  5.             System.out.println(me.getKey()+"::::"+me.getValue());  
  6.         }  
[java] view plaincopy
  1. interface Map  
  2.      { public static interface Entry  
  3.        {  
  4.        public abstract Object getKey();  
  5.        public abstract Object getValue();  
  6.        }  
  7.      }  
  8.      class HashMap implements Map  
  9.      {  
  10.         class Hash implements Map.Entry  
  11.         {  
  12.           public  Object getKey();  
  13.           public  Object getValue();  
  14.         }  
  15.    }  
范例:

  1. import java.util.*;    
  2. public class mapdemo2 {    
  3.     public static void main(String[] args) {    
  4.         Map<String,String> map=new HashMap<String,String>();    
  5.         map.put("01","zhangs");    
  6.         map.put("02""jav12");    
  7.         map.put("03","jv23");    
  8.         //将map集合中的映射关系取出,存入到set集合中,    
  9.         Set<Map.Entry<String, String>>entrySet=map.entrySet();    
  10.         Iterator <Map.Entry<String, String>>it1=entrySet.iterator();    
  11.         while(it1.hasNext())    
  12.         {    
  13.             Map.Entry<String, String>me=it1.next();    
  14.             String key=me.getKey();    
  15.             String value=me.getValue();    
  16.             System.out.print(key+":::"+value);    
  17.         }    
  18.         //先获取map集合的所有键的set集合,keyset();    
  19.         Set<String> keyset=map.keySet();    
  20.         //有了set集合,就可以获取其迭代器    
  21.         Iterator<String> it=keyset.iterator();    
  22.         while(it.hasNext())    
  23.         {    
  24.             String key=it.next();    
  25.             //有了键可以通过map集合的get方法获取其键对应的值    
  26.             String value=map.get(key);    
  27.             System.out.println("key:"+key+"value"+value);    
  28.         }    
  29.     }    
  30. }    
 注意,当发现有映射关系时,可以选择map集合,因为map集合中存放就是映射关系。

范例:map与映射有关,因为map就是键值对的映射

范例:


  1. import java.util.*;    
  2. public class mapdemo31 {    
  3.     public static void demo()    
  4.     {    
  5.         HashMap<String,List<sstudent>>czbk=new HashMap<String,List<sstudent>>();    
  6.     List<sstudent> reyu=new ArrayList<sstudent>();    
  7.     List<sstudent> jiuye=new ArrayList<sstudent>();    
  8.     czbk.put("yureban", reyu);    
  9.     czbk.put("jiuyeban", jiuye);    
  10.     reyu.add(new sstudent("01","zhangshan"));    
  11.     reyu.add(new sstudent("02","zhangshan1"));    
  12.     jiuye.add(new sstudent("01","zhangshan2"));    
  13.     jiuye.add(new sstudent("02","zhangshan3"));    
  14.       //遍历czbk集合,获取所有的教室    
  15.       Iterator<String>it= czbk.keySet().iterator();    
  16.        while(it.hasNext())    
  17.        {    
  18.            String roomName=it.next();    
  19.           List<sstudent> room=czbk.get(roomName);    
  20.            System.out.println(roomName);    
  21.            getInfos(room);    
  22.        }    
  23.     }    
  24.     public static void getInfos(List<sstudent> list)    
  25.     {    
  26.         Iterator<sstudent>it=list.iterator();    
  27.         while(it.hasNext())    
  28.         {    
  29.             sstudent s=it.next();    
  30.             System.out.println(s);    
  31.         }    
  32.     }    
  33.     public static void main(String[] args) {    
  34.          demo();    
  35.         /** HashMap<String,HashMap<String,String>>czbk=new HashMap<String,HashMap<String,String>>();  
  36.            HashMap<String,String> yure=new HashMap<String,String>();  
  37.            HashMap<String,String> jiuye=new HashMap<String,String>();  
  38.            jiuye.put("01","zhaoli");  
  39.            jiuye.put("02","sdfs");  
  40.            czbk.put("yureban", yure);  
  41.            czbk.put("jiuyeban", jiuye);  
  42.            yure.put("01","zhaoli");  
  43.            yure.put("02","sdfs");  
  44.            //遍历czbk集合,获取所有的教室  
  45.           Iterator<String>it= czbk.keySet().iterator();  
  46.            while(it.hasNext())  
  47.            {  
  48.                String roomName=it.next();  
  49.                HashMap<String,String> room=czbk.get(roomName);  
  50.                System.out.println(roomName);  
  51.                getStudentInfo(room);  
  52.            }  
  53.            */    
  54.            //getStudentInfo(jiuye);    
  55.             }    
  56.             public static void getStudentInfo(HashMap<String,String> roomMap)    
  57.             {Iterator<String>it=roomMap.keySet().iterator();    
  58.             while(it.hasNext())    
  59.             {    
  60.                 String id=it.next();    
  61.                 String name=roomMap.get(id);    
  62.                 System.out.println(id+"::"+name);    
  63.             }    
  64.             }    
  65.         }    
  66. class sstudent    
  67. {    
  68.  private String id;    
  69.  private String name;    
  70.  sstudent(String id,String name)    
  71.  {    
  72.      this.id=id;    
  73.      this.name=name;    
  74.  }    
  75.  public String toString()    
  76.  {    
  77.     return id+"::"+name;     
  78.  }     
  79. }   


Arrays:

用于操作数组对象的工具类,里面都是静态方法。

asList方法:将数组转换成list集合。

String[] arr = {"abc","kk","qq"};

List<String> list = Arrays.asList(arr);//将arr数组转成list集合。

将数组转换成集合,有什么好处呢?用aslist方法,将数组变成集合;

可以通过list集合中的方法来操作数组中的元素:isEmpty()、contains、indexOf、set;

注意(局限性):数组是固定长度,不可以使用集合对象增加或者删除等,会改变数组长度的功能方法。比如add、remove、clear。(会报不支持操作异常UnsupportedOperationException);

如果数组中存储的引用数据类型,直接作为集合的元素可以直接用集合方法操作。
如果数组中存储的是基本数据类型,asList会将数组实体作为集合元素存在。

集合变数组:用的是Collection接口中的方法:toArray();

如果给toArray传递的指定类型的数据长度小于了集合的size,那么toArray方法,会自定再创建一个该类型的数据,长度为集合的size。
    如果传递的指定的类型的数组的长度大于了集合的size,那么toArray方法,就不会创建新数组,直接使用该数组即可,并将集合中的元素存储到数组中,其他为存储元素的位置默认值null。
    所以,在传递指定类型数组时,最好的方式就是指定的长度和size相等的数组。

将集合变成数组后有什么好处?限定了对集合中的元素进行增删操作,只要获取这些元素即可。


  1. import java.util.*;    
  2. public class arrayDemo {    
  3.     public static void main(String[] args) {    
  4.           //int arrp[]={2,4,5};    
  5.           //System.out.println(Arrays.toString(arrp));    
  6.           String[]arr={"we","wer","wet"};    
  7.          //把数组变成list集合有什么好处?    
  8.           //  可以使用集合的思想和方法来操作数组中的元素    
  9.           //  注意:将数组变成集合,不可以使用集合的增删方法    
  10.           //  因为数组的长度是固定    
  11.           //  contains   get   indexof()   sublist()    
  12.         //  如果增删,那么会发生unsupportedOperationException    
  13.          List<String>list=Arrays.asList(arr);    
  14.          System.out.println(list.contains("cc"));    
  15.          list.add("aa");//unsupportedOperationException 不支持操作异常    
  16.            System.out.println(list);    
  17.          //  int[] num={2,3,4};    
  18.          Integer[] nums={3,4,4};    
  19.          List<Integer>li=Arrays.asList(nums);    
  20.          //  List<int[]>li=Arrays.asList(num);    
  21.          //  如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素    
  22.            //  如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。    
  23.            System.out.println(li);    
  24.     }    
  25. public static boolean myContains(String[]arr,String key)    
  26. {    
  27.   for(int x=0;x<arr.length;x++)    
  28.   {    
  29.       if(arr[x].equals(key))    
  30.           return true;    
  31.   }    
  32.   return false;    
  33. }    
  34. }    
注意:Jdk5.0新特性:
Collection在jdk1.5以后,有了一个父接口Iterable,这个接口的出现的将iterator方法进行抽取,提高了扩展性。

—————————————————————————————————————————————————————————————————————————

增强for循环:

foreach语句,foreach简化了迭代器。

格式: 增强for循环括号里写两个参数,第一个是声明一个变量,第二个就是需要迭代的容器

for( 元素类型 变量名 : Collection集合 & 数组 ) {
  …

  1. String [] arr = {"a""b""c"};//数组的静态定义方式,只试用于数组首次定义的时候  
  2. for(String s : arr) {  
  3.   System.out.println(s);   
  4. }  

增强for循环和传统for循环的区别:

高级for循环在使用时,必须要明确被遍历的目标。这个目标,可以是Collection集合或者数组,如果遍历Collection集合,在遍历过程中还需要对元素进行操作,比如删除,需要使用迭代器

如果遍历数组,还需要对数组元素进行操作,建议用传统for循环因为可以定义角标通过角标操作元素。如果只为遍历获取,可以简化成高级for循环,它的出现为了简化书写。
 

增强for循环迭代:

原则上map集合是无法使用增强for循环来迭代的,因为增强for循环只能针对实现了Iterable接口的集合进行迭代;

Iterable是jdk5中新定义的接口,就一个方法iterator方法,只有实现了Iterable接口的类,才能保证一定有iterator方法,java有这样的限定是因为增强for循环内部还是用迭代器实现的,而实际上,我们可以通过某种方式来使用增强for循环。


  1. for(Object obj : map.entrySet()) {  
  2.   Map.Entry entry = (Entry) obj;  // obj依次表示Entry  
  3.   System.out.println(entry.getKey() + "=" + entry.getValue());  
  4. }  
注意:

在迭代集合的过程中,不能对集合进行增删操作(会报并发访问异常);可以用迭代器的方法进行操作(子类listIterator:有增删的方法)。
在使用增强for循环时,不能对元素进行赋值;

——————————————————————————————————————————————————

JDK1.5出的几个新特性

1,可变参数


  1. public class paramMethodDemo {    
  2.     public static void main(String[] args) {    
  3.     }    
  4.     //可变参数,其实就是上一种数组参数的简写形式,不用每一次都动手的建立数组对象,只要将要操作的元素作为参数传递即可    
  5.     //隐试将这些参数封装成了数组。    
  6.     public static void show(String str,int... arr)    
  7.     {    
  8.         System.out.println(arr.length);    
  9.     }    
  10.     /*public static void show(int a,int b)  
  11.     {}  
  12.     public static void show(int a,int b,int c)  
  13.     {}*/    
  14. }    
可变参数(...):用到函数的参数上,当要操作的同一个类型元素个数不确定的时候,可是用这个方式,这个参数可以接受任意个数的同一类型的数据。

和以前接收数组不一样的是

以前定义数组类型,需要先创建一个数组对象,再将这个数组对象作为参数传递给函数。现在,直接将数组中的元素作为参数传递即可。底层其实是将这些元素进行数组的封装,而这个封装动作,是在底层完成的,被隐藏了。所以简化了用户的书写,少了调用者定义数组的动作。
如果在参数列表中使用了可变参数,可变参数必须定义在参数列表结尾(也就是必须是最后一个参数,否则编译会失败。)。
如果要获取多个int数的和呢?可以使用将多个int数封装到数组中,直接对数组求和即可。
2,静态导入

staticImport静态导入

静态导入:导入了类中的所有静态成员,简化静态成员的书写。

当类名重名时,需要指定具体的报名,
当方法重名时,指定具备所属的对象或者类。


  1. import static java.util.Collections.*;  //导入了Collections类中的所有静态成员  
静态导入范例:

  1. import java.util.*;    
  2. import static  java.util.Arrays.*;//导入的是arrays这个类中的所有的静态成员    
  3. import java.lang.System.*;//导入了system类中所有静态成员。    
  4. public class StaticImport {    
  5.     public static void main(String[] args) {        
  6.            int[]arr={3,4,5};    
  7.            sort(arr);//Arrays.sort(arr);    
  8.            int index=binarySearch(arr, 1);    
  9.            System.out.println(Arrays.toString(arr));    
  10.        System.out.println(index);    
  11.     }    
  12. }    
3,自动拆装箱:

java中数据类型分为两种:基本数据类型  引用数据类型(对象)

基本---引用   Integer x = new Integer(x);
引用---基本   int num = x.intValue();

4,泛型通配符

可以解决当具体类型不确定的时候,这个通配符就是?  ;当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用 ? 通配符来表未知类型。

5,泛型限定:

    上限:?extends E:可以接收E类型或者E的子类型对象。
    下限:?super E:可以接收E类型或者E的父类型对象。


0 0