集合类 & MAP & 泛型

可以看看这两篇博文   

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());
	}
 }
}

abc1
abc2
abc3

优化:这里循环结束了,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;
	}
	@Override
	public int compareTo(Person p) {
		// TODO Auto-generated method stub
		int 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@659e0bfd
com.leo.bean.Person@659e0bfd
yamiedie:18
com.leo.bean.Person@2a139a55
com.leo.bean.Person@2a139a55
lisi:20
com.leo.bean.Person@15db9742
com.leo.bean.Person@15db9742
wangwu:30
com.leo.bean.Person@6d06d69c
com.leo.bean.Person@6d06d69c
qinshou:60

 

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


通配符 ?

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



如何选择 集合容器

唯一?

    需要 set

          顺序?

                需要 treeset

                不需要 hashset

                 和存储一致:linkedhashset

     不需要 list

            需要频繁增删?

                   需要   linkedlist

                   不需要 arraylist







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值