集合类 & MAP & 泛型

来源:互联网 发布:seo 刷关键词排名工具 编辑:程序博客网 时间:2024/06/06 17:28

可以看看这两篇博文   

http://www.cnblogs.com/mingcn/archive/2010/10/22/JavaContainer.html

http://michaelfly.iteye.com/blog/519484


1.集合类的由来

   

     对象用来封装各种不同的数据,比如person类里装了 string类型的name,int型的age

     但是对象多了咋办,就用集合类来装,person1、person2.。。


2.集合的特点

    

      集合容器只能用来存储对象,注意与数组的区别,数组也可以存储对象,但是数组还能存储基本数据类型。

      集合的长度是可变的,随便你加减操作。而数组是一定的

     

3.不同集合的共性

   

        不同集合容器内部的数据结构不同,所以有所区别,但是他们肯定有共性

        往上抽取,就形成一些共性的框架


        最基本的就是collection接口,里面有各种添加删除判断获取等方法

        注意迭代器,iterator,取出集合里的元素,返回的是一个迭代器对象,用来取出集合里的对象

 

4.常用集合类容器,比如arraylist,collection的实现类

       打印这个arraylist的时候,会打印出其中的所有元素

       removeall移除相同的元素,retainall 保留相同的元素

       迭代器的使用

         hasnext,当还有元素可取时,返回true

         next(),下一个元素

public class Hello { public static void main(String[] args){Collection col = new ArrayList();col.add("abc1");col.add("abc2");col.add("abc3");Iterator it = col.iterator();while(it.hasNext()){System.out.println(it.next());} }}

abc1abc2abc3

优化:这里循环结束了,iteratr还在,next()这个指向下一个的指针还在,占了一点内存,可以利用for循环来写,循环结束就销毁了,这种写法更常见

public static void main(String[] args){Collection col = new ArrayList();col.add("abc1");col.add("abc2");col.add("abc3");for(Iterator it = col.iterator();it.hasNext();){System.out.println(it.next());}

最常用的两个子接口:list和set

list是有序的-存入和取出的顺序是相同的,list有索引,list允许重复

set是hashmap的变种。为了让单列集合元素唯一,不允许重复


关于list的取出方式,除了collection通用的方式(set只有这个),还可以通过遍历位置信息去

demo:给list某个元素后加一个元素,如果list里没有这个元素,则输出整个list

public class Hello { public static void main(String[] args){ List list = new ArrayList();        list.add("abc1"); list.add("abc2"); list.add("abc3");  Iterator it = list.iterator(); while(it.hasNext()){ //add加的是对象,这里返回的应该也是对象 //开始读取 Object obj = it.next(); if(obj.equals("abc2")){ list.add("abc5"); }else {System.out.println("next:"+obj);}  } System.out.println(list); }}

这个时候会报错,打印了第一个元素,然后挂了


为啥呢,因为往list里添加了元素,而iterator不知道

这里不能直接通过list添加,而可以通过列表迭代器来,只有list有一个单独的迭代器

public class Hello { public static void main(String[] args){ List list = new ArrayList();        list.add("abc1"); list.add("abc2"); list.add("abc3"); //不能在迭代器内用list来操作元素 ListIterator it = list.listIterator(); while(it.hasNext()){ //add加的是对象,这里返回的应该也是对象 //开始读取 Object obj = it.next(); if(obj.equals("abc3")){ //通过listIterator来迭代 it.add("abc6"); }else {System.out.println("next:"+obj);}  } System.out.println(list); }}

5.list常用对象  arraylist,linkedlist,vector

vector出现的最早,内部是一个数组,但是可变大小,同步的,创建一个数组,将原来的东西复制进来,100%延长,增删查询都慢

arraylist用来代替vector,内部也是数组,可变大小,不同步的,他是在原有数组上延长,是50%的延长,更省事,关于不同步,上面的例子就很好的说明了,查询快

linkedlist,内部是链表,非同步的,增删元素比较快


6.MAP   和collection是一个级别的接口

但他是键值对,和collection最大的区别


put方法,返回的是之前key对应的value值,第一次存返回的就是null,或者说之前没有值,就是空


常用的实现类 hashmap

 Map<Integer, String> map = new HashMap<Integer, String>();

    想要取值,可以先找到所有key

    6.1 通过getSet获得所有key的set集合,再通过set的迭代器获取每一个键,再通过键获取value

Map<Integer, String> map = new HashMap<Integer, String>(); //获得所有键的set集合 Set<Integer> keyset = map.keySet(); //通过set集合获得迭代器 Iterator<Integer> its = keyset.iterator(); while(its.hasNext()){ //通过迭代器取键 Integer key = its.next(); //通过键取值 String value = map.get(key); System.out.println(key+":"+value); }

6.2 entrySet  返回的是键值关系的set集合,通过把map转成Set,就能拿到一个迭代器,entrySet将映射关系作为对象存储到集合中,而这个映射关系类型是map.entry型

Map<Integer, String> map = new HashMap<Integer, String>(); Set<Map.Entry<Integer, String>> entryset = map.entrySet(); Iterator<Map.Entry<Integer, String>> itss = entryset.iterator(); while(itss.hasNext()){ Map.Entry<Integer, String> me = itss.next(); Integer key = me.getKey(); String value = me.getValue(); System.out.println(key+" : "+value); }

map.entry是一个静态的内部接口,会随着map的加载而加载,entry是映射关系的对象,访问map里的键和值,封装在map内


6.3 values()

返回所有值的collection对象,键唯一,值不唯一

Map<Integer, String> map = new HashMap<Integer, String>(); Collection<String> values = map.values(); Iterator<String> itsss = values.iterator(); while(itsss.hasNext()){ System.out.println(itsss.next()); }

6.4 map的子类

hashtable:内部结构是哈希表,非空,类似于collection中的vector,最早一个,同步的

hashmap:内部是哈希表,允许null作为键值,不是同步的(collection里的set是由hashmap实现的,就是他的一个实例,不过为了保证单列集合的元素唯一性才有的set)

treemap:内部结构是二叉树,不同步,可以对map里的键进行排序


hashtable有一个子类,properties,很生猛,属性集,用来存储键值对型的配置文件,常见与IO结合使用


7.泛型

是一种安全机制,在容器集合里面很常见

对于一些类型不匹配而导致的运行时错误转到编译来发现,也无需强转类型了

当数据类型不是很确定的时候,就加上<>成为泛型,将需要的数据类型传入,其实就是一个参数范围,类似于方法里的形参

只要有带<>的类或者接口,就需要明确类型


运行时,泛型会被去掉,生成的class文件里不带泛型,此即泛型的擦除,为了去兼容运行时的类加载器

由于只在编译时会带上泛型,那么在运行过程中,这些对象都还是object类,这样在实际操作时,本来应该还需要强转,但是强转是由一定隐患的,所以有了补偿机制

,通过在运行时获取类型来强转


以treeset为例

public class Person {    String name;    int age;public Person() {super();// TODO Auto-generated constructor stub}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;}}

public class MyGenericDemo {  public static void main(String[] args) { TreeSet<Person> ts = new TreeSet<Person>();  ts.add(new Person("lisi",20)); ts.add(new Person("wangwu",30)); ts.add(new Person("yamiedie",18)); ts.add(new Person("qinshou",60));  Iterator<Person> it = ts.iterator();  while(it.hasNext()){ Person p = it.next(); System.out.println(p); }  }}

跑起来,挂了,为嘛子,因为treeset是二叉树结构的,需要比较,他有比较器的方法,compare和equal

Exception in thread "main" java.lang.ClassCastException: com.leo.bean.Person cannot be cast to java.lang.Comparable

应该在person类实现一个接口,compare,任何可比较的方法里都有这个接口

先按年龄排序,相等时按名字排序

这里用到了compareTo方法,他是按照第一个字符的ASC码比较,返回差值

public class Person implements Comparable<Person>{    String name;    int age;public Person() {super();// TODO Auto-generated constructor stub}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;}@Overridepublic int compareTo(Person p) {// TODO Auto-generated method stubint temp = this.age-p.age;return temp == 0?this.name.compareTo(p.name):temp;}}

while(it.hasNext()){ Person p = it.next(); System.out.println(p); System.out.println(p.toString()); System.out.println(p.getName()+":"+p.getAge()); }

<pre name="code" class="plain">com.leo.bean.Person@659e0bfdcom.leo.bean.Person@659e0bfdyamiedie:18com.leo.bean.Person@2a139a55com.leo.bean.Person@2a139a55lisi:20com.leo.bean.Person@15db9742com.leo.bean.Person@15db9742wangwu:30com.leo.bean.Person@6d06d69ccom.leo.bean.Person@6d06d69cqinshou:60


另一种比较的方法,equals(object o)  参数不能改类型的


通配符 ?

 ? extends  000    类型范围限制,表明只能接收000及他的子类 



如何选择 集合容器

唯一?

    需要 set

          顺序?

                需要 treeset

                不需要 hashset

                 和存储一致:linkedhashset

     不需要 list

            需要频繁增删?

                   需要   linkedlist

                   不需要 arraylist







0 0