A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

集合框架
    概述

    面向对象语言对事物的描述都是以对象的形式体现的,为了方便对多个对象的操作,就对对象进行存储,集合就是存处对象最常用的一种方式,数据多了用对象存,对象多了就用集合存。
    集合和数组都是容器,但是它们之间是有区别的。
    数组的长度是固定的,集合的长度时刻变得,集合中只能存对象,而数组中还可以存基本数据类型,但数组不能存不同数据类型的对象,集合可以。
    集合作为一个容器,它分了很多种,java对这些容器进行了划分和描述,这些容器有共性也有特性,我们把不同集合间的关系用一张图来表示:

    

    出现这么多容器的原因就是:每一个容器对数据的存储方式都会有不同,这种存储方式我们称之为数据结构。
    
    集合的共性方法
    
    需要注意的是集合中存的并不是对象实体,而是对象的引用或地址。
    根据参阅顶层创建底层的思想,我们先来看Collection接口中的共性方法。
    1,添加
       add(Object obj):add方法的参数类型是Object。以便于接收任意类型对象;
       addAll(Collection c):添加另一个集合中的所有元素。

    2,删除
       remove(Object obj):删除某一个元素;
       removeAll(Collection c);取两个集合的交集,并从调用者中删除这个交集包含
       的所有元素;
       clear():清空集合。

    3,判断。
       contains(Object obj):判断是否包含某元素;
       containsAll(Collection c):判断一个集合是否是另一个集合的子集;
       isEmpty():判断集合是否为空。

    4,获取
       iterator():迭代器;
       size():获取集合的大小。

    5,获取交集。
       retainAll():取交集。
    
    迭代器
    
    取出集合中的元素,实际开发时,我们要做的是取出元素进行操作,并不是简简单单的打印。
    什么是迭代器?
    其实就是集合取出元素的方式。
    集合中存放了元素,想要操作元素,定义内部类进行操作最为方便,这个内部类就完成了取出动作的定义,每个容器中都有这个内部类,以后再产生容器又要定义这个内部类,发现再取出的时候,一般都会做判断和取出动作,所以就把取出方式定义在集合内部,这样取出方式能直接访问集合内的元素,那么取出方式就被定义成了内部类,而每一个容器的数据结构不同,所以取出的动作也不同,但是有共性内容,判断和取出,那么我们可以将共性抽取,这个功能是扩展功能,把这些共性抽取出来形成接口,那么这些内部类都符合一个规则,该规则是Iterator,如何获取集合的取出对象呢?通过一个方法:inerator()。
    其实就相当于我们现实生活中的夹子取娃娃的机器,大家去商场,都会看到这样的机器,每个机器里的夹子都不同,但它们都会对娃娃进行取出等操作,怎么操作,夹子最清楚,而且夹子会去夹机器内部的娃娃,所以我们就把夹子放在了机器内部。
    迭代器中的方法
    hasNext():判断是否还有下一个元素,是就返回true,否则返回false;
    next():获取下一个元素;
    remove:删除元素;
    我们通过一段代码来演示如何用迭代方法取出集合中的元素:
import java.util.*;
class  IteratorDemo
{
        public static void main(String[] args)
        {       
                getElement();
        }
        public static void getElement()
        {
                ArrayList al = new ArrayList();
                //1,添加元素。
                al.add("java01");
                al.add("java02");
                al.add("java03");
                al.add("java04");
                Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素。
                while(it.hasNext())//判断是否有下一个元素
                {
                        System.out.println(it.next());//获取元素并打印
                }
        }
}

运行的结果是:

    
  
    List集合

    Collection

       |--List: 元素是有序的,可重复,因为该集合体系有索引;

          |--ArrayList:底层数据结构是数组结构,它的特点是查询速度快,增删稍
          慢,线程不同步;

          |--LinkedList:底层使用的是链表结构,它的特点是增删速度快,查询比较
          慢,线程不同步;

          |--Vector:底层是由的数据结构是数组结构,和ArrayList一样,它是线程同
          步的;
    
    List集合的共性方法

    凡是可以操作角标的方法,都是List集合所特有的方法。
    
    增加元素:add(index,element);
              add(index,collection);

    删除元素:remove(index);删除成功,返回true,失败返回false,

    修改元素:set(index,element);

    查找元素:get(index );
              subList(fromIndex,toIndex);
              listIterator();
    
    ListIterator列表迭代器
    它是List集合特有的迭代器,是Iterator的子接口。
    我们获取到的iterator迭代器,只能对元素进行判断取出和删除操作,如果我们想在迭代过程中,进行添加或者其他操作,那就要用到列表迭代器,否则就会产生并发访问的安全隐患。
import java.util.*;
class  IteratorDemo
{
        public static void main(String[] args)
        {       
                getElement();
        }
        public static void getElement()
        {
                ArrayList al = new ArrayList();
                //1,添加元素。
                al.add("java01");
                al.add("java02");
                al.add("java03");
                al.add("java04");
                Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素。
                while(it.hasNext())//判断是否有下一个元素
                {
                        Object obj = it.next();
                        if(obj.equals("java02"))
                                al.add("java007");
                        System.out.println("obj="+obj);//获取元素并打印
                }
        }
}

编译是没有问题的,我们看一下运行结果:

    
    
    ConcurrentModificationException:这个是并发访问异常!在迭代时,不可以通过集合对象的方法操作几盒中的元素,会发生并发修改异常,所以在迭代时,只能用迭代器的方法操作元素,而iterator的方法时有限的,只能对元素进行判断,取出和删除操作,要使用添加等其他操作,就要使用的Iterator的子接口ListIterator,该接口只能通过List集合的listIterator方法获取。
    列表迭代器除了增删操作外,还有set修改方法,进行逆向迭代:hasPrevious(),判断前面有没有元素,previous(),获取前一个元素。
    
    Vector中的枚举:Enumaeration

    枚举是Vector集合特有的取出元素的方式。
    其实枚举和迭代是一样的,因为枚举的名称和方法的名称过长,所以被迭代取代了。
    举个例子来对枚举取出元素的方式进行演示
import java.util.*;
class  VectorDemo
{
        public static void main(String[] args)
        {       
                getElement();
        }
        public static void getElement()
        {
                Vector v = new Vector();
                v.add("java01");
                v.add("java02");
                v.add("java03");
                Enumeration en = v.elements();
                while(en.hasMoreElements())//判断是否有下一个元素
                {
                        System.out.println(en.nextElement());//获取元素并打印
                }
        }
}

运行结果:

       

    LinkedList集合

    特有方法:
    1、增加元素
               addFirst();
               addLast();
    2、获取元素:获取元素,但不删除元素。
               getFirst();
               getLast();
    3、删除元素:获取并删除元素。
               removeFirst();
               removeLast();
    在jdk1.6之后出现了替代的方法add--->offer;get--->peek;remove--->poll;在删除和获取元素时,如果列表为空,这些方法不会发生NoSuchElementException,会返回一个null。
    练习:使用LinkedList模拟一个堆栈或者队列数据结构。
/*
需求:使用LinkedList模拟一个堆栈或者队列数据结构。
堆栈:先进后出  如同一个杯子。
队列:先进先出 First in First out  FIFO 如同一个水管。
*/
import java.util.*;
class DuiLie
{
        private LinkedList link;

        DuiLie()
        {
                link = new LinkedList();
        }
       
        public void myAdd(Object obj)//模拟add方法
        {
                link.addFirst(obj);
        }
        public Object myGet_1()//模拟删除方法
        {
                return link.removeFirst();
        }
        public Object myGet_2()//模拟删除方法
        {
                return link.removeLast();
        }
        public boolean isNull()//模拟判断集合是否为空
        {
                return link.isEmpty();
        }

}
class  LinkedListTest
{
        public static void main(String[] args)
        {
                DuiLie dl = new DuiLie();
                dl.myAdd("java01");
                dl.myAdd("java02");
                dl.myAdd("java03");
                dl.myAdd("java04");

                while(!dl.isNull())
                {
                        //System.out.println(dl.myGet_1());//先进后出,模拟堆栈
                        System.out.println(dl.myGet_2());//先进先出,模拟队列
                }
        }
}

    ArrayList练习一:去除ArrayList集合中的重复元素。
import java.util.*;
/*
去除ArrayList集合中的重复元素。
思路:定义一个临时容器,对指定的集合进行遍历,遍历过程中判断这个元素是否在我们定义的临时容器中,
如果不在就将该元素添加到这个临时定义的容器中,最后将这个集合作为返回值,返回给调用者。
*/
class ArrayListTest
{
        public static void main(String[] args)
        {
                ArrayList al = new ArrayList();

                al.add("java01");
                al.add("java02");
                al.add("java01");
                al.add("java02");
                al.add("java01");
                al.add("java03");
                System.out.println(al);               
                al = singleElement(al);
                System.out.println(al);               
        }
        public static ArrayList singleElement(ArrayList al)
        {
                //定义一个临时集合容器。
                ArrayList newAl = new ArrayList();

                Iterator it = al.iterator();

                while(it.hasNext())
                {
                        Object obj = it.next();

                        if(!newAl.contains(obj))
                                newAl.add(obj);
                }
                return newAl;
        }
}

    ArrayList练习二:将自定义对象作为元素存到ArrayList集合中,并去除重复元素,比如:存人对象,同姓名同年龄,视为同一个人,为重复元素。
import java.util.*;
/*
需求:将自定义对象作为元素存到ArrayList集合中,并去除重复元素。
比如:存人对象。同姓名同年龄,视为同一个人。为重复元素。
思路:
1,对人描述,将数据封装进人对象。
2,定义容器,将人存入。
3,取出。
*/
class Person
{
        private String name;
        private int age;
        Person(String name,int age)
        {
                this.name = name;
                this.age = age;
        }       
        public boolean equals(Object obj)//复写equals方法,因为从Object类继承来的equals方法只是比较地址值
        {
                if(!(obj instanceof Person))
                        return false;
                Person p = (Person)obj;
                return this.name.equals(p.name) && this.age == p.age;//名字,姓名都不相同才是同一个对象
        }
        public String getName()//实际开发get,set都要有!
        {
                return name;
        }
        public int getAge()
        {
                return age;
        }
}
class ArrayListTest2
{
        public static void sop(Object obj)
        {
                System.out.println(obj);
        }
        public static void main(String[] args)
        {
                ArrayList al = new ArrayList();
                al.add(new Person("lisi01",30));
                al.add(new Person("lisi02",32));
                al.add(new Person("lisi02",32));
                al.add(new Person("lisi04",35));
                al.add(new Person("lisi03",33));
                al.add(new Person("lisi04",35));
                al = singleElement(al);               
                Iterator it = al.iterator();
                while(it.hasNext())
                {
                        Person p = (Person)it.next();
                        sop(p.getName()+"::"+p.getAge());
                }
        }
        public static ArrayList singleElement(ArrayList al)
        {
                ArrayList newAl = new ArrayList();
                Iterator it = al.iterator();
                while(it.hasNext())
                {
                        Object obj = it.next();
                        if(!newAl.contains(obj))//contains remove依赖的都是equals方法
                                newAl.add(obj);
                }
                return newAl;
        }
}

运行结果是:

    

    List集合判断元素是否相同,依据是元素的equals方法,这个equals方法在底层是自动被调用的,remove,contains依赖的都是该方法,数据结构不同,依赖的比较方法是不同的,ArrayList和LinkedList依赖的都是equals方法。

    Set集合

    特点:
    Set集合中的元素是无序的,也就是说存入和取出的顺序不一定一致,元素不可以重复。
    Set集合的功能和Collection的功能是一致的。
    常见的子类
    HashSet:底层数据结构是哈希表,是线程不安全的,不同步。
    TreeSet:底层是二叉树数据结构,是线程不安全的,不同步。
   
    HashSet集合特点:
    HashSet集合存数据是按照哈希表来存储的,存入时,先比较哈希值是否相同,如果不同,再比较是否是同一个对象,所以说HashSet是按照hashCode和equals来保证对象的唯一性的。
    所以说,在我们创建一个对象是,要复写hashCode和equals方法,有可能这个对象要放到HashSet集合中。
    HashSet集合判断和删除依赖的也是hashCode和equals方法,先判断hashCode,在判断equals。

    TreeSet集合的特点:
    可以对set集合中的元素进行排序。
    TreeSet对存入集合对象的要求是必须具备比较性,让对象实现去实现Comparable接口,并复写接口中的compareTo方法,这种方式我们称之为元素的自然排序,下面我们用代码来进行演示(这里为了演示排序,我就不考虑重复元素了):

import java.util.*;
/*
需求:往TreeSet集合中存储自定义对象学生,想按照学生的年龄进行排序。
*/
class Student implements Comparable//该接口强制让学生具备比较性。
{
        private String name;
        private int age;

        Student(String name,int age)
        {
                this.name = name;
                this.age = age;
        }
        public int compareTo(Object obj)//复写compareTo方法,自定义比较方式;
        {
                if(!(obj instanceof Student))
                        throw new RuntimeException("不是学生对象");
                Student s = (Student)obj;
                int num = new Integer(this.age).compareTo(new Integer(s.age));//Integer实现了Comparable,已具备比较性;
                if(num==0)
                        return this.name.compareTo(s.name);//String也具备比较性,首要条件相同时,要比较次要条件;
                return num;
        }
        public String getName()
        {
                return name;

        }
        public int getAge()
        {
                return age;
        }
}
class TreeSetDemo
{
        public static void main(String[] args)
        {
                TreeSet ts = new TreeSet();
                ts.add(new Student("lisi02",22));
                ts.add(new Student("lisi007",20));
                ts.add(new Student("lisi09",19));
                ts.add(new Student("lisi08",24));
                Iterator it = ts.iterator();
                while(it.hasNext())
                {
                        Student stu = (Student)it.next();
                        System.out.println(stu.getName()+"..."+stu.getAge());
                }
        }
}

运行结果是:

    
   
    TreeSet的第二种排序方式
    对元素进行排序的原理:
    1,让元素自身具备比较性;
    2,让集合具备比较性。
    当元素自身不具备比较性时,或者说元素所具备的比较性不是我们所需要的,这时就需要让集合自身具备比较性,java提供了这种便利,它让集合初始化的时候就有比较方式,这个方式就是Comparator比较器,我们可以自定义一个比较器,然后将这个比较器作为参数传递给集合的构造函数,这样,集合就具备比较性了。
    如果元素和集合都具备比较性,比较方式以比较器为主。
    怎么去定义一个比较器呢?
    1,定义一个类,实现Comparator接口;
    2,复写compare方法;
    3,将比较器对象作为参数传递给集合的构造函数。
    用代码进行演示:

/*
需求:将学生对象存进TreeSet集合中,对学生对象按姓名进行排序。
*/
class Student implements Comparable//该接口强制让学生具备比较性。
{
        private String name;
        private int age;
        Student(String name,int age)
        {
                this.name = name;
                this.age = age;
        }

        public int compareTo(Object obj)
        {               
                if(!(obj instanceof Student))
                        throw new RuntimeException("不是学生对象");
                Student s = (Student)obj;
                int num = new Integer(this.age).compareTo(new Integer(s.age));
                if(num==0)
                        return this.name.compareTo(s.name);
                return num;
        }

        public String getName()
        {
                return name;

        }
        public int getAge()
        {
                return age;
        }
}
class TreeSetDemo
{
        public static void main(String[] args)
        {
                TreeSet ts = new TreeSet(new MyCompare());

                ts.add(new Student("lisi02",22));
                ts.add(new Student("lisi02",21));
                ts.add(new Student("lisi007",20));
                ts.add(new Student("lisi09",19));
                ts.add(new Student("lisi06",18));
                ts.add(new Student("lisi06",18));
                ts.add(new Student("lisi007",29));
                Iterator it = ts.iterator();
                while(it.hasNext())
                {
                        Student stu = (Student)it.next();
                        System.out.println(stu.getName()+"..."+stu.getAge());
                }
        }
}
class MyCompare implements Comparator//定一一个比较器
{
        public int compare(Object o1,Object o2)//复写compare方法
        {
                Student s1 = (Student)o1;
                Student s2 = (Student)o2;
                int num = s1.getName().compareTo(s2.getName());//按照姓名进行比较
                if(num==0)
                        return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));               
                return num;
        }
}

打印结果是:

    

    泛型

    概述:泛型是JDK1,5以后出现的新特性,用于解决安全问题,是一个安全机制(类型安全机制)。
    在泛型出现以前,我们通过定义Object来接收任意类型的参数,然而这种方式带来的缺点是要做强制的类型转换,如果要进行强制类型转换,我们需要提前知道实际参数类型是什么,才能进行转换,而且对于类型转换错误这种异常,在编译时期,编译器可能不提示错误,在运行时才出现,这样就有安全隐患。
    泛型出现后的好处:1,将运行时起出现的问题ClassCastException转移到了编译时
                         期,方便与程序员解决问题,让运行时期的安全问题减少;
                      2,避免了强制转换的麻烦。
    用代码来演示:

import java.util.*;
class GenericDemo
{
        public static void main(String[] args)
        {
                ArrayList<String> al = new ArrayList<String>();//尖括号内放的就是我们限定的只能装到集合中的元素;
                al.add("adadada");
                al.add("dfgergre");
                al.add("gerdfdf");
                al.add("bhgfht");
                Iterator<String> it = al.iterator();//迭代器中设置泛型;
                while(it.hasNext())
                {
                        String s = it.next();//不用再做强制转换;
                        System.out.println(s+":::"+s.length());
                }
        }
}

    

    发现编译时这个不安全操作的提示消失了,而且我们也不用在做强制类型转换。
            
    泛型的应用
    格式:通过<  >来接收要操作的引用数据类型。
    在java提供的对象时,什么时候写泛型?
    通常在集合框架中很常见,只要见到< >就要定义泛型。
    Collection<E>,E没有任何意义,相当于形式参数,一个变量,就是Element,元素,其实<>就是来接收类型的,当使用集合时,将集合中要存储的数据类型作为参数,传递到<>中即可,如同函数中传参数一样。
   注意:我们在上边对对象进行比较的equals方法,复写的是Object方法,Object没有泛型,所以那个Object必须写,对象也必须要做强转。

    泛型类

    集合的迭代器,比较器都涉及到泛型了,我们也可以在自己定义的类中使用泛型,以前我们都是用Object来接收任意类型的参数,现在我们可以通过泛型来完成。
    接下来用代码进行演示:

class Worker
{
}
class Student
{
}
//泛型前做法。
class Tool
{
        private Object obj;
        public void setObject(Object obj)
        {
                this.obj = obj;
        }
        public Object getObject()
        {
                return obj;
        }
}
//泛型类
class Utils<QQ>//这就是个泛型类
{
        private QQ q;
        public void setObject(QQ q)
        {
                this.q = q;
        }
        public QQ getObject()
        {
                return q;
        }
}


class  GenericDemo3
{
        public static void main(String[] args)
        {

                Utils<Worker> u = new Utils<Worker>();

                u.setObject(new Student());
                Worker w = u.getObject();//在这里,定义泛型后,不需要再做强转
        }
}

      
    那么我们在什么时候要定义泛型呢?
    当类中要操作的引用数据类型不确定时,早期定义Object来完成扩展,现在定义泛型来完成扩展(基本数据类型不确定,定义不了),泛型能把运行时的错误转移到编译时期,也避免了类型的强转,集合就是泛型类。

    泛型方法
    通过分析,我们发现,泛型类是有局限性的,对象一固定,要操作的类型就确定了,泛型类的对象明确要操作的具体数据类型后,所有方法要操作的类型就已经固定了,为了让不同的方法操作不同的数据类型,而且类型还不确定,那么可以将泛型定义到方法中。
    泛型定义在方法上,放到返回值类型前边,修饰符的后边。
    特殊之处:静态方法不可以访问类上定义的泛型,如果静态方法操作的引用数据类型不确定,可以将反省定义在方法上。
    
    泛型接口
    将泛型定义在接口上,用代码演示下吧:

//泛型定义在接口上。
interface Inter<T>
{
        void show(T t);
}
class InterImpl implements Inter<String>//实现此接口时已明确要操作的类型是String;
{
        public void show(String t)
        {
                System.out.println("show :"+t);
        }
}
class InterImpl<T> implements Inter<T>//实现此接口时也不明确要操作的类型;
{
        public void show(T t)
        {
                System.out.println("show :"+t);
        }
}
class GenericDemo5
{
        public static void main(String[] args)
        {

                InterImpl<Integer> i = new InterImpl<Integer>();
                i.show(4);
                //InterImpl i = new InterImpl();
                //i.show("haha");
        }
}

    泛型限定
    泛型限定是用于泛型扩展用的。
    泛型限定有两个限定:向上限定和向下限定。
    ?:通配符,也可以理解为占位符,不明确具体类型时用"?"表示,使用?后,就不能在使用传进来类型的对象的特有方法了,因为类型不明确,该类型对应的对象能调用的方法也是不明确的。
    ? extends E:向上限定,可以接受E或者E的子类型。
    ? super E:向下限定,可以接受E或者E的父类型。
    
    Map集合

    特点:该集合存储的是键值对,一对一对往里存,而且要保证该集合键的唯一性。
    
    常见的子类

    Hashtable:底层是哈希表数据结构,不可以存入null键null值,该集合是线程同步的,jdk1.0出现,效率低。
    HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的,将hashtable替代,jdk1.2出现,效率高。
    TreeMap:底层是二叉树数据结构,线程不同步,可以用于给map集合中的键进行排序。
    
    常用方法

    添加
        put(K key,V value):如果添加相同的键,后添加的值会覆盖原有键对应值,返
        回被覆盖的值;
        putAll(Map <? extends K,? extends V> m):添加一个集合;
    删除
        clear():清空
        remove(Object key):删除指定键值对;
    判断
        containsKey(Object key):判断键是否存在;
        containsValue(Object value):判断值是否存在;
        isEmpty():判断是否为空;
    获取
        get(Object key):通过键获取对应的值;
        size():获取集合的长度;
        values():获取Map集合中所有值,返回一个Collection集合;

    从集合中取出元素的方法:keySet(),entrySet()---重点内容
    keySet:key键,Set集合,将map集合中所有的键存入到了set集合,因为set集合具备迭代器,所以可以根据迭代器取出所有的键,然后根据键get方法获取所有的值。
    原理:将map集合转成set集合,在通过迭代器取出。

    entrySet:将map集合中的映射关系存入到set集合中,而这个关系的数据类型就是:Map.Entry,Entry其实就是Map中的一个static内部接口。
    将它定义在内部的原因就是:只有有了Map集合,有了键值对,才会有键值的映射关系,关系属于Map集合中的一个内部事物,而且该事物在直接访问Map集合中的元素,然后在使用getValue和getKey方法获取值和键。
    
    练习:每一个学生都有对应的归属地,学生student,地址String,每一个学生都有自己的名字和年龄,同姓名同年龄的视为同一个学生,要保证学生的唯一性,并对学生年龄对象进行升序排序。

/*
需求:每一个学生都有对应的归属地,学生student,地址String,每一个学生都有自己的名字和年龄
同姓名同年龄的视为同一个学生,要保证学生的唯一性,并使用比较器对学生对象的年龄进行升序排序。
步骤:
1,描述学生对象;
2,因为学生是以键形式存在的,所以可以把学生键用TreeMap集合进行存储;
3,获取TreeMap集合中的元素。
*/
import java.util.*;
class Student implements Comparable<Student>//实现Comparable接口,让学生具备比较性
{
        private String name;
        private int age;
        Student(String name,int age)
        {
                this.name = name;
                this.age = age;
        }
        public String getName()
        {
                return name;
        }
        public int getAge()
        {
                return age;
        }
        public String toString()
        {
                return name+":::"+age;
        }
        public int hashCode()
        {
                return name.hashCode()+age*34;
        }
        public boolean equals(Object obj)
        {
                if(!(obj instanceof Student))
                        throw new ClassCastException("不是学生类");
                Student s = (Student)obj;
                return this.name.equals(s.name) && this.age==s.age;
        }
        public int compareTo(Student s)//复写compareTo方法,自定义比较内容
        {
                int num = this.name.compareTo(s.name);
                if(num==0)
                        return new Integer(this.age).compareTo(new Integer(s.age));
                return num;
        }
}
class MapTest
{
        public static void main(String[] args)
        {
                Map<Student,String> tm = new TreeMap<Student,String>(new MyComp());//将学生对象存入TreeMap中;
                tm.put(new Student("zhangsan",23),"beijing");
                tm.put(new Student("lisi",21),"shanghai");
                tm.put(new Student("wangwu",31),"shenzhen");
                tm.put(new Student("zhaoliu",17),"wuhan");
                tm.put(new Student("zhouqi",18),"tianjin");
                /*
                方法一:用entrySet方法取出集合中的键值;
                Set<Map.Entry<Student,String>> ts = tm.entrySet();
                Iterator<Map.Entry<Student,String>> it = ts.iterator();
                while(it.hasNext())
                {
                        Map.Entry<Student,String> me = it.next();
                        Student str = me.getKey();
                        String addr = me.getValue();
                        System.out.println(str+"="+addr);
                }
                */
                //方法二:用keySet方法取出集合中的键值;
                Set<Student> ts = tm.keySet();
                Iterator<Student> it = ts.iterator();
                while(it.hasNext())
                {
                        Student str = it.next();
                        String addr = tm.get(str);
                        System.out.println("姓名:"+str.getName()+",<span style="white-space:pre">        </span>年龄:"+str.getAge()+"----家庭地址:"+addr);
                }
        }
}
class MyComp implements Comparator<Student>//自定义比较器
{
        public int compare(Student s1,Student s2)
        {
                int num = new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
                if(num==0)
                        return s1.getName().compareTo(s2.getName());
                return num;
        }
}

运行的结果是:

    

    Map扩展知识:一对多,原本把学生的id和姓名也作为键值对,发现可以直接把这两个属性封装成学生对象,把房间名和学生对象作为键值对传到map集合中,然后不同的学生对象放在List集合中。
    用代码来体现:
import java.util.*;
class Student
{
        private String name;
        private int id;
        Student(String name,int id)
        {
                this.name = name;
                this.id = id;
        }
        public String toString()
        {
                return name+".."+id;
        }
}
class MapTest
{
        public static void main(String[] args)
        {
                Map<String,List<Student>> hm = new HashMap<String,List<Student>>();//Map集合中还有List集合;
                List<Student> yure = new ArrayList<Student>();//预热班,放的是预热班的学生;
                List<Student> jiuye = new ArrayList<Student>();//就业班,放的是就业班的学生;
                hm.put("yure",yure);//将预热班教师名称作为键,预热班学生集合作为值存到Map集合中;
                hm.put("jiuye",jiuye);//将预热班教师名称作为键,预热班学生集合作为值存到Map集合中;
                yure.add(new Student("zhangsan",1));//将学生放到预热班集合中;
                yure.add(new Student("lisi",3));
                jiuye.add(new Student("wangwu",3));
                jiuye.add(new Student("zhaoliu",2));
                Set<String> keySet = hm.keySet();
                Iterator<String> it = keySet.iterator();
                while(it.hasNext())//取出教师名称和对应的学生对象
                {
                        String roomName = it.next();
                        List<Student> room = hm.get(roomName);
                        System.out.println(roomName);
                        Iterator<Student> it1 = room.iterator();
                        while(it1.hasNext())
                        {
                                Student str = it1.next();
                                System.out.println(str);
                        }
                }
        }
}

运行结果是:

 

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马