zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    stm32 IO模式
    stm32的ADC
    bsp
    stm32的硬件调试设置
    RTC实时时钟
    快手2019笔试题 “回文子串" 解题思路
    C++内存修改器开源代码
    FC游戏修改教程(hack)小白文。
    GLFW+GLEW搭建opengl环境(备忘)
    8086 IO读写操作
  • 原文地址:https://www.cnblogs.com/foreverzd/p/3416829.html
Copyright © 2011-2022 走看看