zoukankan      html  css  js  c++  java
  • java基础集合框架——List、Set、Map概述(java集合一)

    为什么会出现集合类?

    面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,出现集合


    数组与集合同是容器,有什么不同呢?

    数组长度是固定的,集合长度是可变的

    数组中可以存储基本数据类型,集合只能存储对象

    集合类的特点

    集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象

    基本的集合框架如图




    为什么会出现这么多的容器呢?

    因为每一个容器对数据的存储方式都有不同,这个存储方式称为数据结构

    集合框架分析

    Collection子类

    java.util.Collection [I]  
    +--java.util.List [I]  
       +--java.util.ArrayList [C]  
       +--java.util.LinkedList [C]  
       +--java.util.Vector [C]  
          +--java.util.Stack [C]  


    Set子类

                    
    +--java.util.Set [I]  
       +--java.util.HashSet [C]  
       +--java.util.SortedSet [I]  
          +--java.util.TreeSet [C]  


    Map集合及子类

    java.util.Map [I]  
    +--java.util.SortedMap [I]  
       +--java.util.TreeMap [C]  
    +--java.util.Hashtable [C]  
    +--java.util.HashMap [C]  
    +--java.util.LinkedHashMap [C]  
    +--java.util.WeakHashMap [C]  



    表格分析

    接口 实现类 历史实现类
    List ArrayList Vector
      LinkedList stack
    Set TreeSet  
      HashSet  
    Map HashMap HashTable
      TreeMap Properties






          

    List

    List继承自Collection接口。List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组,List允许有重复元素


    常用子类特点分析


    Vector 内部是数组数据结构,是同步的,增删查询都很慢

    ArrayList 内部是数组数据结构,是不同步的,查询速度快

    LinkedList 内部是链表结构,是不同步的,增删元素很快


    LinkedList

    底层使用的链表数据结构,特点是:增删速度快,查询慢

    LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在 LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。

        注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:
    List list = Collections.synchronizedList(new LinkedList(...)); 
    LinkedList  l  = new LinkedList();  
                l.addFirst("java");  
                l.addFirst("java1");  
                l.addFirst("java2");  
                l.addFirst("java3");  
      
      
    * 在JDK1.6以后,出现的方法  
    *   
    * offerFirst()  
    * offerLast()  
    * peekFirst()  
    * peekLast()  
    * 获取元素,但不删除元素,如果集合中没有元素,会出现null  
    * pollFirst()  
    * pollLast()  
    * 获取元素,但是元素被删除,如果集合中没有元素,会出现null  

    ArrayList

    ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。

    size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。
        每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并 没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。
        和LinkedList一样,ArrayList也是非同步的(unsynchronized)。
    底层使用的是数组结构,特点:查询速度很快,但是增删稍慢,默认长度是10;然后百分之50延长

    ArrayList的常见操作

    ArrayList arrayList = new ArrayList();  
            // 添加元素  
            arrayList.add("java1");  
            arrayList.add("java2");  
            arrayList.add("java3");  
            arrayList.add("java4");  
      
            //直接在控制台上输出集合中元素的信息  
            System.out.println(arrayList);// [java1, java2, java3, java4]  
            // 在指定位置添加元素  
            arrayList.add(2, "world");  
            System.out.println(arrayList);// [java1, java2, world, java3, java4]  
            // 删除指定位置的元素  
            arrayList.remove(2);  
            System.out.println(arrayList);// [java1, java2, java3, java4]  
            // 修改元素  
            arrayList.set(2, "java224");  
            System.out.println(arrayList);// [java1, java2, java224, java4]  
            // 通过角标获取元素  
            System.out.println(arrayList.get(1));// java2  
            // 获取所有元素  
            //第一种方法   
            for (int i = 0; i < arrayList.size(); i++) {  
                System.out.println(arrayList.get(i));  
            }  
            //第二种方法  
            Iterator it = arrayList.iterator();  
            while (it.hasNext()) {  
                System.out.println(it.next());  
            }  
      
            // 通过indexOf获取对象的位置  
            System.out.println(arrayList.indexOf("java2"));  
            // 获取指定区域的元素  
            List sb = arrayList.subList(1, 3);  


    去除ArrayList中的重复元素

    /** 
         * 去除ArrayList中的重复元素 
         * @param l 
         * @return 
         */  
        private static ArrayList med8(ArrayList<Object> l) {  
      
            ArrayList<Object> li = new ArrayList<Object>();  
            Iterator it = l.iterator();  
            while(it.hasNext()){  
                Object obj = it.next();  
                if(!li.contains(obj)){  
                    li.add(obj);  
                }  
            }  
            return li;  
      
        }  


    对ArrayList中的数据进行排序的操作
    public static void main(String[] args) {  
            //创建集合  
            ArrayList<String> arrayList = new ArrayList<String>();  
            //添加元素  
            arrayList.add("adsf");  
            arrayList.add("uytf");  
            arrayList.add("hjk");  
            arrayList.add("wedcv");  
            arrayList.add("kngfsf");  
            arrayList.add("wqqs");  
            //没有进行排序前  
            System.out.println(arrayList.toString());//[adsf, uytf, hjk, wedcv, kngfsf, wqqs]  
              
            //对集合中的元素信息进行排序  
            Collections.sort(arrayList);  
            System.out.println(arrayList.toString());//[adsf, hjk, kngfsf, uytf, wedcv, wqqs]  
          
            //使用自定义比较器的方法,按照字符串的长度来进行排序  
            Collections.sort(arrayList,new StringSortComparator());  
            System.out.println(arrayList.toString());//[hjk, adsf, uytf, wqqs, wedcv, kngfsf]  
        }  
      
    }  
      
    //自定义比较器,按照字符串的长度进行比较原则  
    class StringSortComparator implements Comparator<String>{  
      
        @Override  
        public int compare(String arg0, String arg1) {  
            //比较两个字符串的长度  
            int number = arg0.length()-arg1.length();  
            //==0说明两个字符串的长度一样,再进行内容比较  
            if(number==0){  
                return arg0.compareTo(arg1);  
            }  
            return number;  
        }  
          
    }  



    listIterator  List集合中特有的迭代器


    在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificatinException异常

    所以在使用迭代器的时候,只能用迭代器的方法操作元素,但是Iterator的方法是有限的,只能对元素进行判断,取出,删除的操作,如果想要其他的操作,如添加,修改等,就需要使用其接口,ListIterator

    该接口只能通过List集合的listIterator方法获取

    ArrayList<String> al = new ArrayList<String>();  
             ListIterator its= al.listIterator();  
             while(its.hasNext())  
             {  
                 String  string = (String) its.next();  
             //its.hasNext())   判断迭代指针后是否有元素  
             //its.hasPrevious() 判断迭代指针前是否有元素  
                           
             }  
               //以倒着取出元素  
             while(its.hasPrevious())  
             {  
                 String string = (String) its.previous();  
             }  

    Vector

    Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的 Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常

    底层是数组数据结构,线程同步,被ArrayList替代了,长度为10,然后百分之百延长
        </pre><pre name="code" class="java">Vector<String> vector = new Vector<String>();  
                // 向集合中添加元素  
                vector.add("java");  
                vector.add("java1");  
                vector.add("java2");  
                vector.add("java3");  
                // 通过枚举的方式取出集合中的元素  
                Enumeration en = vector.elements();  
                while (en.hasMoreElements()) {  
                    String string = (String) en.nextElement();  
          
                }  
                // 通过迭代器的方式取出数据  
                Iterator<String> iterator = vector.iterator();  
                while (iterator.hasNext()) {  
                    String string = iterator.next();  
                }  

    Stack

    Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop方 法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈

    Set

    Set继承自Collection接口。Set是一种不能包含有重复元素的集合,Set最多有一个null元素。

    在使用Set集合的时候,应该注意:
    1、为Set集合里的元素的实现类实现一个有效的equals(Object)方法。
    2、对Set的构造函数,传入的Collection参数不能包含重复的元素。
    常见子类及特点:
    HashSet 内部数据结构是哈希表,是不同步的。
    TreeSet 可以对Set集合中的元素进行排序,是不同步的


    HashSet

    <1> 此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证集合的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。

    <2> HashSet不是同步的,需要用以下语句来进行S同步转换

    1. Set s = Collections.synchronizedSet(new HashSet(...));  

    <3> 是如何保证元素的唯一性?

    是通过元素的两个方法,hashCode和equals来完成,如果元素的HashCode值相同,才会判断equals来完成

    如果元素的HashCode值不同,不会调用equals

    <4> 对于判断元素是否还在,以及删除等操作,依赖的方法是元素的hashCode和equals方法


    往HashSet集合中存入自定义对象

    public class ListDemoClass {    
        
        public static void main(String[] args) {    
            //新建集合    
                    HashSet hs = new HashSet();    
                    //向集合中添加元素    
                    hs.add("java2");    
                    hs.add("java3");    
                    hs.add("java1");    
                    hs.add("java4");    
                    hs.add("java5");    
                    //注:add方法的返回值为boolean true代表添加元素成功    
                        
                    //使用迭代器的方法将集合中的元素数据取出    
                    //获取迭代器    
                    Iterator iterator = hs.iterator();    
                    //取出数据    
                    while(iterator.hasNext()){    
                        Object next = iterator.next();    
                        System.out.println("hs中的数据为  :"+next+"");    
                    }    
        }    
        
    }   


    往HashSet集合中存入自定义对象

    定义要进行存储的对象类

    public class PersonInfo {    
        // 姓名和年龄相同为同一个人,重复元素    
        private String name;    
        private int age;    
        
        PersonInfo(String name, int age) {    
                this.name = name;    
                this.age = age;    
            }    
        
        public int hashCode() {    
            return name.hashCode();    
        }    
        
        public String getName() {    
            return name;    
        }    
        
        public int getAge() {    
            return age;    
        }    
        
        //进行比较的方法    
        public boolean equals(Object obj) {    
            if (!(obj instanceof PersonInfo))    
                return false;    
            PersonInfo pe = (PersonInfo) obj;    
            return this.name.equals(pe.name) && this.age == pe.age;    
        }    
        
    }  

    编写储存数据的测试类

    public class ListDemoClass {    
        
        public static void main(String[] args) {    
            // 往hAashSet集合中存入自定义对象    
            // 姓名和年龄相同为同一个人,重复元素    
            HashSet hs = new HashSet();    
            //向集合中添加元素    
            hs.add(new PersonInfo("lishi", 22));    
            hs.add(new PersonInfo("lishi1", 23));    
            hs.add(new PersonInfo("lishi2", 24));    
            hs.add(new PersonInfo("lishi3", 25));    
            hs.add(new PersonInfo("lishi3", 25));    
            hs.add(new PersonInfo("lishi3", 25));    
            Iterator it = hs.iterator();    
            while (it.hasNext()) {    
                //取出集合中的元素    
                PersonInfo pe = (PersonInfo) it.next();    
                System.out.println( "person name is " + pe.getName()+"and age is "+pe.getAge());    
            }    
        
        }   


    编译运行调试



    可以看到,我们向其中添加了六条数据,但实际上集合中只添加了四条数据,因为其中有两条数据是相同的,也就是说那两条数据与我们集合中现有的数据name 各age 是一致的

    TreeSet

    <1> 可以对集合中的元素进行排序

    <2> 里面存储的元素必须具有可比性

    <3> TreeSet排序的第一种方式为  让元素自身具有比较性,元素需要实现compareable接口,覆盖compareTo方法,这种方式也是元素的自然顺序,或者叫默认顺序


    向TreeSet中储存String类型的数据

    public class ListDemoClass {    
        
        public static void main(String[] args) {    
        
            // 新建集合    
            TreeSet ts = new TreeSet();    
            //向集合中添加元素    
            ts.add("aaa");    
            ts.add("aoa");    
            ts.add("ara");    
            ts.add("aea");    
            //获取取迭代器    
            Iterator it = ts.iterator();    
            //循环取出集合中的元素,并将取出的元素输出在控制台上面    
            while (it.hasNext()) {    
                System.out.println(it.next());    
            }    
        
        }  


    可以看到,集合中储存的数据以按照其自然顺序进行了排序

    //创建集合  
            TreeSet<String> treeSet = new TreeSet<String>();  
            //添加元素  
            treeSet.add("adsf");  
            treeSet.add("uytf");  
            treeSet.add("hjk");  
            treeSet.add("wedcv");  
            treeSet.add("kngfsf");  
            treeSet.add("wqqs");  
            //输出储存的数据  
            System.out.println(treeSet.toString());//[adsf, hjk, kngfsf, uytf, wedcv, wqqs]  
             


    按照自定义的比较规则进行集合中元素排序

    这里是按字符串的长度来进行排序

    //将集合中的String类型的数据按照自定义的比较方法按长度由大到小进行排序   
            //创建集合  
            TreeSet<String> treeSet = new TreeSet<String>(Collections.reverseOrder(new StringSortComparator()));  
            //添加元素  
            treeSet.add("adsf");  
            treeSet.add("uytf");  
            treeSet.add("hjk");  
            treeSet.add("wedcv");  
            treeSet.add("kngfsf");  
            treeSet.add("wqqs");  
            //输出储存的数据  
            System.out.println(treeSet.toString());//[kngfsf, wedcv, wqqs, uytf, adsf, hjk]  
              
    //自定义比较器,按照字符串的长度进行比较原则  
    class StringSortComparator implements Comparator<String>{  
      
        @Override  
        public int compare(String arg0, String arg1) {  
            //比较两个字符串的长度  
            int number = arg0.length()-arg1.length();  
            //==0说明两个字符串的长度一样,再进行内容比较  
            if(number==0){  
                return arg0.compareTo(arg1);  
            }  
            return number;  
        }  
    }  

    向TreeSet中储存自定义对象

    在其中存储自定义对象的时候,必须使自定义对象具有可比性,那么可以实现 Comparable接口,然后复写compareTo方法,在其中定义比较对象顺序的方法发生

    public class PersonBean implements Comparable {    
        
        private String name;    
        private int age;    
        
        PersonBean(String name, int age) {    
            this.name = name;    
            this.age = age;    
        }    
        
        public String getName() {    
            return name;    
        }    
        
        public int getAge() {    
            return age;    
        }    
        
        @Override    
        public int compareTo(Object obj) {    
            if (!(obj instanceof PersonBean))    
                throw new RuntimeException();    
            /**  
             * 在这里定义比较对象大小的方法  
             * 先进行年龄的比较,年龄不相等再进行姓名的比较  
             * 如果年龄与姓名都相等,那么就代表同一个对象  
             */    
            PersonBean pe = (PersonBean) obj;    
            if (this.age > pe.age)    
                return 1;    
            if (this.age == pe.age) {    
                return this.name.compareTo(pe.name);    
            }    
        
            return -1;    
        }    
    }   


    建立测试类

    public class ListDemoClass {    
        
        public static void main(String[] args) {    
        
            // 向这个集合中存储自定义对象    
            TreeSet ts = new TreeSet();    
            ts.add(new PersonBean("lishi", 22));    
            ts.add(new PersonBean("lishi1", 23));    
            ts.add(new PersonBean("lishi3", 25));    
            ts.add(new PersonBean("lishi4", 25));    
        
            //获取迭代器,取出其中的元素    
            Iterator it = ts.iterator();    
            while (it.hasNext()) {    
                PersonBean pe = (PersonBean) it.next();    
                System.out.println(pe.getAge() + "  " + pe.getName());    
            }    
        
        }  



    可以看到输出的结果 ,先按照年龄进行排序储存,如果年龄相同,再按照姓名进行排序储存,如果姓名也相同,则代表是同一对象 ,则不进行储存


    向TreeSet中传入比较器进行排序

    这时需要让容器自身具备比较性,

    那么需要定义比较器 ,将比较器对象作为参数传递给TreeSet 集合的构造函数

    当两种排序都存在时,以比较器为主

    那么可以定义一个类,实现Comparator接口,覆盖compare方法

    新建储存对象,并实现Comparator接口,在compare方法中宝比较规则

    public class PersonBean implements Comparable {    
        
        private String name;    
        private int age;    
        
        PersonBean(String name, int age) {    
            this.name = name;    
            this.age = age;    
        }    
        
        public String getName() {    
            return name;    
        }    
        
        public int getAge() {    
            return age;    
        }    
        
        @Override    
        public int compareTo(Object obj) {    
            if (!(obj instanceof PersonBean))    
                throw new RuntimeException();    
            /**  
             * 在这里定义比较对象大小的方法  
             * 先进行年龄的比较,年龄不相等再进行姓名的比较  
             * 如果年龄与姓名都相等,那么就代表同一个对象  
             */    
            PersonBean pe = (PersonBean) obj;    
            if (this.age > pe.age)    
                return 1;    
            if (this.age == pe.age) {    
                return this.name.compareTo(pe.name);    
            }    
        
            return -1;    
        }    
    }   


    自定义一个比较器

    import java.util.Comparator;    
    import java.util.HashSet;    
    import java.util.Iterator;    
    import java.util.TreeSet;    
        
    class CustomCompare implements Comparator {    
        public int compare(Object obj1, Object obj2) {    
            //获取将要进行比较的两个对象    
            PersonBean p1 = (PersonBean) obj1;    
            PersonBean p2 = (PersonBean) obj2;    
            //先进行比较两个对象中的name是否相等,如果相等,那么将返回0    
            int num = p1.getName().compareTo(p2.getName());    
            //如果name相等,那么再比较age的大小     
            if (num == 0) {    
                if (p1.getAge() > p2.getAge())    
                    return 1;    
                if (p1.getAge() == p2.getAge())    
                    return 0;    
                return -1;    
            }    
            return num;    
        }    
    }   


    新建测试类:

    public class ListDemoClass {    
        
        public static void main(String[] args) {    
        
            // 向这个集合中存储自定义对象    
            TreeSet ts = new TreeSet(new CustomCompare());    
            ts.add(new PersonBean("lishi", 22));    
            ts.add(new PersonBean("lishi1", 23));    
            ts.add(new PersonBean("lishi3", 25));    
            ts.add(new PersonBean("lishi3", 26));    
            ts.add(new PersonBean("lishi3", 24));    
            ts.add(new PersonBean("lishi4", 25));    
        
            // 取出集合中的元素数据,并将相关信息输出在控制台上    
            Iterator it = ts.iterator();    
            while (it.hasNext()) {    
                PersonBean pe = (PersonBean) it.next();    
                System.out.println(pe.getAge() + "  " + pe.getName());    
            }    
        
        }   




    以字符串的长度为排序规则进对TreeSet集合中的String类型的数据进行排序

    首先自定义一个比较器

    class StringLengthCompare implements Comparator {    
        public int compare(Object obj1, Object obj2) {    
            //获取将要进行比较的字符串    
            String s = (String) obj1;    
            String s1 = (String) obj2;    
            int num = new Integer(s.length()).compareTo(new Integer(s1.length()));    
            if (num == 0) {    
                return s.compareTo(s1);    
        
            }    
            return num;    
        }    
    }   


    新建测试类:

    public class ListDemoClass {    
        
        public static void main(String[] args) {    
        
            // 按照字符长度排序    
            // 字符串具有比较性,但是不是所需要的    
            // 向这个集合中存储自定义对象    
            //新建TreeSet集合并将自定义比较 器传给集合    
            TreeSet ts = new TreeSet(new StringLengthCompare());    
            //向集合中添加不同长度的String字符串    
            ts.add("ggg");    
            ts.add("aaa");    
            ts.add("swed");    
            ts.add("asdfv");    
            ts.add("tyrfg");    
            //获取迭代器,循环取出集合中的数据并输出在控制台上    
            Iterator it = ts.iterator();    
            while (it.hasNext()) {    
                String s = (String) it.next();    
                System.out.println(s);    
            }    
        
        }    


    Map


    Map没有继承Collection接口。也就是说Map和Collection是2种不同的集合。Collection可以看作是(value)的集合,而Map可以看作是(key,value)的集合。
    Map接口由Map的内容提供3种类型的集合视图,一组key集合,一组value集合,或者一组key-value映射关系的集合。

    常见子类及特点
    HashTable 底层是哈希表,是同步的,null不可以做键值进行储存
    HashMap 底层是哈希不结表结构,不同步,null可以做键值进行储存
    TreeMap 底层是二叉树结构,是不同步的,

    Hashtable

    Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。
    由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方 法。


    特别说明

       hashCode和equals方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相 同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如 果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode()方法,能加快哈希 表的操作。
      
        如果相同的对象有不同的hashCode,对哈希表的操作会出现意想不到的结果(期待的get方法返回null),要避免这种问题,只需要牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。
        Hashtable是同步的。


    HashMap

    HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null ke

        // 新建一个集合  
                Map<Integer, String> map = new HashMap<Integer, String>();  
                // 向map中添加10条数据  
                for (int i = 0; i < 10; i++) {  
                    map.put(i, "java" + i);  
                }  
          
                System.out.println(map);// {0=java0, 1=java1, 2=java2, 3=java3, ...}  
                  
                  
                //删除指定位置的元素  
                map.remove(0);  
                System.out.println(map);//{1=java1, 2=java2, 3=java3,...}  
                  
                //判断指定位置的元素是否在在  
                boolean containsKey = map.containsKey(0);  
                System.out.println(containsKey);//false  
                  



    取出map集合中的数据 方式一

    //取出方式一   
            //获取集合中的元素  
            //先获取所有的key,然后再去获取所的value  
            Set<Integer> keySet = map.keySet();  
            Iterator<Integer> iterator = keySet.iterator();  
            while (iterator.hasNext()) {  
                //获取对应的key  
                Integer next = iterator.next();  
                //根据key值获取对应的值   
                String string = map.get(next);  
                  
            }  

    取出map集合中的数据 方式二

    // 取出方式二  
            //将map中的键值的映射关系 作为对象储存到set集合中去  
            Set<Entry<Integer,String>> entrySet = map.entrySet();  
            //获取迭代器  
            Iterator<Entry<Integer, String>> iterator2 = entrySet.iterator();  
            while(iterator2.hasNext()){  
                Entry<Integer, String> entry = iterator2.next();  
                //获取key  
                Integer key = entry.getKey();  
                //获取对应的value  
                String value = entry.getValue();  
            }  


    取出map集合中的数据 方式

    //取出方式三  
            Collection<String> values = map.values();  
            Iterator<String> iterator3 = values.iterator();  
            while(iterator3.hasNext()){  
                String valueString = iterator3.next();  
            }  
    TreeMap

    创建一个类对象,作为key储存在TreeMap集合中
      
    class Person {  
        //定义对象的两个私有属性  
        private String name = "张三";  
        private String age = "22";  
        private Person person;  
          
        public Person() {  
            super();  
        }  
          
        public Person(String name, String age) {  
            super();  
            this.name = name;  
            this.age = age;  
        }  
        public String getName() {  
            return name;  
        }  
        public String getAge() {  
            return age;  
        }  
       
    //创建一个集合  
            TreeMap<Person,String> treeMap = new TreeMap<Person,String>();  
            //向TreeMap中添加数据   
            treeMap.put(new Person("张三", "10"), "山西");  
            treeMap.put(new Person("李四", "15"), "上海");  
            treeMap.put(new Person("王五", "9"), "山西");  
            treeMap.put(new Person("小六", "13"), "北京");  
            //输出元素信息  
            System.out.println(treeMap);  

    编译运行;出现错误
    1. Exception in thread "main" java.lang.ClassCastException: Person cannot be cast to java.lang.Comparable  
    2.     at java.util.TreeMap.compare(Unknown Source)  
    3.     at java.util.TreeMap.put(Unknown Source)  
    4.     at MapDemoTest.main(MapDemoTest.java:15)  

    走到这里,我们可以看到在进行元素储存的过程的时候就已经出现错误了

    解决方案 (一)

    使我们的对象本身具有比较性,实现Comparable接口,在compareTo方法定义比较规则为根据姓名来排序
    class Person implements Comparable<Person>{  
        //定义对象的两个私有属性  
        private String name = "张三";  
        private String age = "22";  
        private Person person;  
          
        public Person() {  
            super();  
        }  
          
        public Person(String name, String age) {  
            super();  
            this.name = name;  
            this.age = age;  
        }  
        public String getName() {  
            return name;  
        }  
        public String getAge() {  
            return age;  
        }  
      
        @Override  
        public int compareTo(Person arg0) {  
            return this.name.compareTo(arg0.name);  
        }  
         

    这样后,我们再进行编译运行就要吧发现可以进行了

    解决方案(二)
    定义一个比较器,然后将比较器传给集合
    // 自定义一个比较器,在compare中定义比较规则  
    // 这里定义的比较规则是Person中的姓名进行比较  
    class MapSortCompar implements Comparator<Person> {  
      
        @Override  
        public int compare(Person o1, Person o2) {  
      
            return o1.getName().compareTo(o2.getName());  
        }  
      
    }  


    然后将比较器传递给集合
    // 创建一个集合  
            TreeMap<Person, String> treeMap = new TreeMap<Person, String>(new MapSortCompar());  
            // 向TreeMap中添加数据  
            treeMap.put(new Person("张三", "10"), "山西");  
            treeMap.put(new Person("李四", "15"), "上海");  
            treeMap.put(new Person("王五", "9"), "山西");  
            treeMap.put(new Person("小六", "13"), "北京");  
            // 输出元素信息  
            Set<Person> keySet = treeMap.keySet();  
            Iterator<Person> iterator = keySet.iterator();  
            while(iterator.hasNext()){  
                Person key = iterator.next();  
                String values = treeMap.get(key);  
                System.out.println("key is "+key.getName()+"value is "+values);  
            }  
    编译运行:控制台会输出
    1. key is 小六value is 北京  
    2. key is 张三value is 山西  
    3. key is 李四value is 上海  
    4. key is 王五value is 山西  





    注:add方法的参数类型是Object 以便于接收任意类型的对象

    集合中存储的都是对象的引用(地址);

    什么是迭代器呢?

    其实就是集合的取出元素的方式

    把取出方式定义在集合的内部,这样取出方式就可 直接访问集合内容的元素

    那么取出方式就被定义在成了内部类

    而每一个容器的数据结构不同,所以取出的动作细节也不一样,但是都有共性内容---判断和取出,那么可以将写共性抽取,那么这些内部类都符合一个规则,该规则就是Iterator

    如何获取集合的取出对象呢?

    通过一个对外提供的方法

    iterator()

  • 相关阅读:
    cookie封装
    禁止网站某页面被频繁刷新(验证)
    $(...) is null
    svn: E155004: Working copy '/data/www' locked.
    svn checkout不带根文件夹方法
    IIS LUA推荐
    给Elasticsearch 5.2.2 设置用户权限 how to setting security for elasticsearch on windows
    怎么部署 .NET Core Web项目 到linux
    怎么删除Elasticsearch里的index内容
    Windows 计划任务 Task Schedule 怎么 运行 .bat文件
  • 原文地址:https://www.cnblogs.com/miaozhenzhong/p/5930927.html
Copyright © 2011-2022 走看看