java集合体系

集合:

数学里的概念把若干数据放在一起,看成一个整体;而在面向对象的世界里,为了方便对对象的操作,体现了其如何以哪种方式储存(数据结构),集合是储存对象的 容器!

1、相比与数组:

数组:是JAVA语言内置的数据类型,
    它是一个线性的序列,所以它可以快速的访问其他的元素。

    但是速度是要有代价的,当你创建了一个数组之后,它的容量就固定了

    如果发现有越界现象,会报RuntimeException异常错误

数组与集合的一点区别:

1:数组是固定长度的;集合可变长度的(自由添加)。

2:数组可以存储基本数据类型,也可以存储引用数据类型;
        集合只能存储引用数据类型。(对象的引用)

3:数组存储的元素必须是同一个数据类型;
        集合存储的对象可以是不同数据类型。       
View Code

 

 

2、集合体系:

  1.  Collection 接口: 

    有了集合就要对其操作,那么具体操作有哪些?为此,抽取各个容器之共性,将其封装为一个接口,可以从面向对象的概念来理解;
    接口方法看帮助文档:Collection家族中 两个主要下属,List,Set,(同为接口)   

  2. Iterator 接口: (迭代器)

    因为不同容器对于对象的储存细节不同,但是有两点还是相同的:判断是否有,取出来,为此也抽取为接口用来规定这种取出集合的方式;各个集合对接口的实现,其遍历时对外提供 iterator()方法;此返回 iterator 接口的一个直接实现,

      如: abstractList 中,内部类实现了接口  Iterator
        public Iterator<E> iterator() {
          return new Itr();    // 内部类 实现了Iterator
        }

  3. list接口:

    有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复

    具体实现类:

      (1) ArrayList:【查询性】

底层的数据结构是数组,线程不同步,ArrayList替代了Vector,查询元素的速度非常快

      (2) LinkedList:【增删性】

底层的数据结构是链表,线程不同步,增删元素的速度非常快。

      (3) Vector:

底层的数据结构就是数组,线程同步的,Vector无论查询和增删都巨慢

    注意:

对于list集合,底层判断元素是否相同,其实用的是元素自身的equals方法完成的。

所以建议元素都要复写equals方法,建立元素对象自己的比较相同的条件依据。

    List  的示例:

package com.collection;
import java.util.*;
public class MethodOfList {
    
    public static void main(String args[])
    {
        method1();
        method2();
        method3();
        
        methdoOfLinkedList();
        
        selfHasEquals();
        
    }
    public static void method1(){
        ArrayList al = new ArrayList();
        al.add("abc0");
        al.add("abc1");
        al.add("abc3");
        al.add(0, "abc5");           //表明是从  index = 0 时存取的: 
        al.set(2, "替代");
        _iterator(al);
        
        /*    abc5
            abc0
            替代
            abc3
        */
    }
    private static void method2(){
        ArrayList al = new ArrayList();
        al.add("abc0");
        al.add("abc1");
        al.add("abc3");
        
        ArrayList all = new ArrayList();
        all.add("abc0");
        all.add("abc1");
        all.add("abc5");
        
        all.retainAll(al);     //           交集
        _iterator(all);
        
        /*
             abc0
            abc1
        */    
    }
    private static void method3(){
        ArrayList al = new ArrayList();
        al.add("abc0");
        al.add("abc1");
        al.add("abc2");
        al.add("abc3");
        al.add("abc1");
        
        al.remove("abc1");     
      //只会remove()最先找到的
        
        _iterator(al);          
        
        System.out.println("4:"+al.get(3)); 
/*        4:abc1
        由此方法我们可以用for循环来迭代,不用迭代器,
        但是时间比迭代器慢多了,
        
        List集合因为角标有了自己的获取元素的方式,
*/        
        for(int i = 0; i < al.size(); i++)
        {
//            System.out.println(al.toString());    
            System.out.println(al.get(i)) ;
            if(i==0)
                al.add("临死添加");
            if(i==1)
                al.set(2, "零食修改");
        }
        
        /*abc0
        abc2
        零食修改
        abc1
        临死添加
        */
        
    }
    private static void _iterator(Collection coll) {
            /*        
            当然:如果嫌弃方法不够的话,可以获得   ListIterator
            (List集合特有的迭代器,
            该列表迭代器接口具备了对元素的增、删、改、查的动作)
            */
    
        for(Iterator iterator = coll.iterator(); iterator.hasNext() ;)
        {
            /*String s = (String)iterator.next();  
            System.out.println(s);*/   
            /*            
               假如add(2); ----装箱为Integer,不能转为String                                      
               jdk1.5增加了泛型,在编译时期动态查询引用数据类型,
               达到与实际主观add的效果() 就是集合内类型一致
            */        
            System.out.println(iterator.next());
        }
        System.out.println();
    }    
    
    
    public static void methdoOfLinkedList(){
        LinkedList<String> ld = new LinkedList<String>();
        ld.add("1");
        ld.add("2");        
        ld.add("3");        
        ld.add(null);

        ld.addFirst("addfirst");
        ld.addLast("不就是add么?");
        _iterator(ld);
        /*
         新增方法:
         
        获得:
        getFirst()   getLast() ; 
        获取链表中的第一个元素。如果链表为空,
    抛出NoSuchElementException;
        
        peekFirst();
        获取链表中的第一个元素。如果链表为空,返回null。
        peekLast();
        
        public E getFirst() {
            if (size==0)
                throw new NoSuchElementException();
        
            return header.next.element;
            }
        
        移除:
        removeFirst()            NoSuchElementException;
        removeLast();
        
        pollFirst();获取链表中的第一个元素,但是会删除链表中的第一个元素。
        如果链表为空,返回null。
        pollLast();
        
         
        */
    
        ld.removeAll(ld); //全部移除
        _iterator(ld);
        
//        System.out.println(ld.getFirst());
        System.out.println(ld.peek());            //   null
        
    }
    public static void selfHasEquals()
    {
        ArrayList<Str> al = new ArrayList<Str>();
        Str temp = new Str("2");
        al.add(new Str("1"));
        al.add(new Str("2"));
        //如果没有覆写equals,,,是不会找到,返回false
        System.out.println(al.contains(temp));
    }
        
}

class Str{
    String s  ;
    Str(String s){
        this.s = s;
    }
    /*public boolean equals(Object t){
        return this.s.equals(((Str)t).s);    
    }*/    
}
View Code

 

 

 

  4. Set接口:

无序(存入和取出顺序有可能不一致),不可以存储重复元素。必须保证元素唯一性

    (1)  HashSet:【唯一性】

底层数据结构是哈希表,线程是不同步的。无序,高效;对于ArrayList集合,判断元素是否存在,或者删元素底层依据都是equals方法。HashSet集合,判断元素是否存在,或者删除元素,底层依据的是hashCode方法和equals方法。

        为什么由这两个实现呢??:

查类库:
        HashSet<E>   
            private transient HashMap<E,Object> map;
            private static final Object PRESENT = new Object();

        ---->     public boolean add(E e) {
            return map.put(e, PRESENT)==null;
           }
        --->  HashMap<K,V>     ----public V put(K key, V value) 


   public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

 由上我们也可以知道,是因为map集合具备着键的唯一性,其实set集合就来自于map,set集合底层其实用的就是map的方法。
View Code

    (2) TreeSet: 【 排序性】

用于对Set集合进行元素的指定顺序排序,排序需要依据元素自身具备的比较性。如果元素不具备比较性,在运行时会发生ClassCastException异常。

      Set  的示例:

package com.collection;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

public class MethodOfSet {
    public static void main(String args[])
    {
        testMethodOfHashSet();
        testMethodOfTreeSet();
        testTime();
    }
    private static void testMethodOfHashSet()
    {
        HashSet<Object> hs = new HashSet<Object>();
        hs.add("a");
        hs.add("b");
        hs.add("a");
        _iterator(hs);        
/*        b
        a
        体现无序性 和 唯一性
*/    
    }
    private static void testMethodOfTreeSet() {
        TreeSet<Object> ts = new TreeSet<Object>();
        ts.add("x");
        ts.add("z");
        ts.add("y");
        ts.add("y");
        _iterator(ts);
        
/*        x
        y
        z*/    
    }
    
    private static void  _iterator(Set<Object> hs)
    {
        for(Iterator<Object> i = hs.iterator(); i.hasNext();)
        {
            System.out.println(i.next());
        }
        System.out.println();
    }
    
    
    private static void testTime() {
        long start ,end ;
        int temp ;
        Set<Integer> st = new HashSet<Integer>();
        for(int i = 0; i < 1008611;i++)
        {
            st.add(i);
        }
        
        start = System.currentTimeMillis();
        for(Iterator<Integer> i = st.iterator();i.hasNext();)
        {
            temp = i.next();
        }
        end = System.currentTimeMillis();
        System.out.println("---iterator:"+(end-start));
        
        start = System.currentTimeMillis();
        for(Integer t:st)
        {
            temp = t ;
        }
        end = System.currentTimeMillis();
        System.out.println("---增强 for:"+(end-start));
        
    /*    ---iterator:25
        ---增强 for:24
        二者不相上下:
    */        
    }
    
}
View Code

 

 

  5、map接口:

        public interface Map<K,V> 

   所有键值对构成的集合,对此种集合集成为一个接口,便于扩展,Map集合存储和Collection有着很大不同:

    1. Collection一次存一个元素;Map一次存一对元素(一对元素也可以看做一个整体,封装为对象,)。
    2. Collection是单列集合;Map是双列集合。
    3.  Map中的存储的一对元素:一个是键,一个是值,键与值之间有对应(映射)关系。

  总之,要保证map集合中键的唯一性。

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


  Map.Entry<K,V>

  一对键值本身看做一个对象,由于有获得键,获得值,两种共性,因此抽离出此接口;getKey() ;getValue() :setValue(V value)

  map的实现类中,含有内部实现类:

    Entry: static class Entry<K,V> implements Map.Entry<K,V>

    so ,entry是访问键值关系的入口,是map的入口,访问的是map中的键值对,

    但由于内部类无法导入,故使用接口回调

  转换:

     map中的所有Entry 转化 为 entrySet (返回:set<Map.Entry<k,v>>

    也可以将所有键值转为: Set keySet();

    Map 的示例:

package com.collection;
import java.util.*;

public class MethodOfMap {
    
    public static void main(String args[])
    {
        methodOfHashMap();    
        
        methodOfTreeMap();
        
        Example();
    }
        

    private static void methodOfHashMap() {
        Map<Integer,String> m = new HashMap<Integer,String>();
        m.put(1, "a");
        m.put(2, "a");
        m.put(3, "a");
        m.put(2, "b");      //  
        
        //出map集合中所有元素
        
        Set<Map.Entry<Integer, String>> s1 = m.entrySet();
        for(Iterator<Map.Entry<Integer, String>> i = s1.iterator(); i.hasNext(); )
        {
            Map.Entry<Integer, String> e = i.next();
            System.out.println(e.getKey()+" : "+e.getValue());
            e.setValue(e.getKey()+""+e.getValue());
            //根据键值来修改:
        }
        
        System.out.println();
        
        Set<Integer> s2 = m.keySet();
        for(Iterator<Integer> i = s2.iterator(); i.hasNext(); )
        {
            Object k = i.next();
            Object v = m.get(k);
            System.out.println(k+" : "+v);
        }
        /*    
         1 : a
        2 : b
        3 : a
    
        1 : 1a
        2 : 2b
        3 : 3a
    */

    }    
    private static void methodOfTreeMap() {
        Map<Integer,String> m = new TreeMap<Integer,String>();
        m.put(51, "v");
        m.put(72, "e");
        m.put(33, "l");
        m.put(42, "o");     
        Set<Integer> s = m.keySet();
        Iterator<Integer> i = s.iterator();    
        while(i.hasNext()){
            Integer k = i.next();
            String v = m.get(k);
            System.out.println(k+"-"+v);
            
        }
/*        33-l
        42-o
        51-v
        72-e*/
        
    }    
    public static void Example()
    {    /*
        一字符串:String str="1,1,0";
        数字使用逗号隔开,统计出每个数字出现的次数。使用map<数字,次数>;*/
        
        String target = "10,16,10,16,17,11,16,10,16,10,17,11,16,13,13,11,16,10";
        String s[] = target.split(",");
        Map<String ,Integer> m = new HashMap<String ,Integer>();
        for(int i = 0 ;i <s.length ;i++)
        {
            if(m.containsKey(s[i]))
            {
                m.put(s[i],m.get(s[i])+1);
            }
            else{
                m.put(s[i], 1);
            }
        }
        for(Iterator<Map.Entry<String ,Integer>> i = m.entrySet().iterator() ;i.hasNext();)
        {
            Map.Entry<String, Integer> me = i.next();
            System.out.println(me.getKey()+":"+me.getValue());
            /*    10:5
                17:2
                16:6
                13:2
                11:3
             */
        }
    }
}
View Code

 

 

 

posted @ 2013-11-10 17:05  寻影  阅读(1477)  评论(0编辑  收藏  举报