------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
|--HashSet:底层数据结构使用的是哈希表,线程不同步。因此无序,高效。
HashSet保证无序,不重复的原因分析:
无序:由于当我们添加元素时,这个元素存放到哪里由该元素的hash值确定的,而取出的顺序是按照Hash表取出的,因此一般存取的顺序都不一致,造成无序。
不重复:当我们向HashSet中插入元素时,首先会计算该元素的Hash值,然后与集合中元素一一比较,如果没有相等的,那么就表示无相同元素,那么就直接插入Hash表,如果有相同的,那么就调用该元素的equals方法与那个Hash值一样的元素进行二次比较,如果这次比较结果为true,那么就表示二者为同一元素,那么就会丢弃当前元素,如果结果为false,就表示不是同一元素,那么就会在其Hash值下顺延出一片空间用于存储当前元素。
|--TreeSet:底层数据结构使用的是二叉树。线程不同步。因此无序,高效。
TreeSet保证无序,不重复的原因分析:
无序:由于我们向二叉树中添加元素时,要保证元素的存储时有序的,因此会导致存入和取出的顺序不一致,造成无序。
不重复:当我们向二叉树添加元素时,会调用元素的compareTo或者compare方法,将当前元素与集合中元素一一比较,如果小于当前元素,那么就存放到当前元素的左子树中,如果大于就存放到当前元素的右子树中,如果等于那么就直接丢弃。
对于HashSet集合,判断元素是否存在,或者删除元素依赖hashCode方法和equals方法。
也就是说对于HashSet来说,判断两个元素相等,不仅要equals返回true,同时也要hashCode的返回值一致才算相等元素。
对Set集合进行元素的指定顺序排序,排序需要依据元素自身具备的比较性或者比较器的比较方法。
如果元素不具备比较性,在运行时会发生ClassCastException异常。
因此需要元素实现Comparable接口,强制让元素具备比较性。
注意:排序时,如果主要条件(年龄)一致,那么一定要比较一下次要条件(姓名)。
方式1:
利用元素的compareTo方法按照元素自然顺序的排序。我们知道存入TreeSet集合中的元素必须实现Comparable接口,因此必须实现compareTo方法。
方式2:
利用比较器,也就是定义一个类实现comparator类,复写其compare方法。
两种方式比较:
使用方式1,优势是简单,劣势是我们只能按照自然顺序排序,如果需求改变了,那就要去改源代码,这是不建议,也是灾难性的,因为修改源代码可能会导致大量的问题出现。而方式2就不存在这个问题,如果需求改变了,那我们就可以定义一个比较器来提供一种新定义的新的比较方式,这样我们在不改变源代码的前提下,又达到了需求。这种方式更加灵活安全。因此开发一般采用方式2。
//Hash表存储自定义对象
//思路:问题在于相同元素的唯一性,也就是要自定义相等这个规则
//存入人对象,设定:同名同年龄为同一个人
package com.helong.hashsetdemo;
import java.util.*;
class Person
{private String name;private int age;Person(String name,int age){this.name=name;this.age=age;}public String getName(){return name;}public int getAge(){return age;}//复写hashCode方法,否则每个人对象的hash值都是不同的public int hashCode(){//思路:该方法返回的hash值应该是由姓名和年龄来决定的,这样才可以保证不同对象的hash值唯一return this.name.hashCode()+this.age*33;//字符串本身就有自己的hash值(常量池中的地址)再加上年龄*33,作为该对象的hash值//乘以33主要是为了尽量避免出现两个对象名不同,年龄不同,但是一相加之后最后的值相同//结果有一个没有被存储的情况发生。}//复写equals方法,自定义相等规则public boolean equals(Object obj)//注意别写成了equals(Person p)这是重载不是复写了{System.out.println("equals");if(!(obj instanceof Person))throw new RuntimeException("对象非人对象");Person p=(Person)obj;return this.name.Name())&&this.age=Age();}
}
class HashSetDemo
{public static void main(String[] args) {HashSet hs = new HashSet();hs.add(new Person("helong01",22));hs.add(new Person("ldy",22));hs.add(new Person("ldy",22));hs.add(new Person("ldy",18));hs.add(new Person("helong02",22));hs.add(new Person("helong02",22));for(Iterator it = hs.iterator();it.hasNext();){Person p=(Person)(it.next());System.out.println("Name:"Name()+",Age:"Age());}}
}
运行图:
//两种TreeSet集合排序方式
//1.元素具备可比性
//2.集合自身具备针对此元素的可比性
//存入人对象,希望按照年龄进行排序,且同名同年龄为相同对象
package setdemo;
import java.util.*;
//元素自身具有可比性
class Person /*implements Comparable*/
{private String name;private int age;Person(String name,int age){this.name=name;this.age=age;}public String getName(){return name;}public int getAge(){return age;}/*public int compareTo(Object obj){if(!(obj instanceof Person))throw new RuntimeException("对象非人对象");//此处只能抛运行时异常,因为接口中compareTo并未声明异常Person p=(Person)obj;int tempAge()-p.getAge();if(temp==0){//如果年龄相同,那我们应该按照其次要条件姓名进行排序Name()Name());//字符串对象已经实现了Comparable接口,具有可比性}return temp;}*/
}//集合自身具有可比性
class MyComparator implements Comparator
{public int compare(Object o1,Object o2){if(!(o1 instanceof Person)||!(o2 instanceof Person))throw new RuntimeException("对象非人对象");Person p1=(Person)o1,p2=(Person)o2;int tempAge()-p2.getAge();if(temp==0){Name()Name());}return temp;}
}
class TreeSetDemo
{public static void main(String[] args) {//让元素具备可比性来达到排序的效果//TreeSet ts = new TreeSet();//让集合资深具备可比性TreeSet ts = new TreeSet(new MyComparator());//将比较器作为构造函数的参数ts.add(new Person("helong",22));ts.add(new Person("helong",18));ts.add(new Person("ldy",22));ts.add(new Person("helong",22));ts.add(new Person("ldy",18));ts.add(new Person("abc",18));ts.add(new Person("abbb",18));for(Iterator it = ts.iterator();it.hasNext();){Person p=(Person)(it.next());System.out.println("Name:"Name()+",Age:"Age());}}
}
运行图:
//按照字符串长度排序(次要条件是字符串本身的自然顺序)
/*
思路:
由于不可能改变String类的compareTo方法,那么我们只能使用比较器来解决
在比较器中:1.首要条件是长度。2.次要条件是自然顺序
*/
package settest;
import java.util.*;
class MyCompare implements Comparator
{public int compare(Object o1,Object o2){System.out.println(o1+"===="+o2);if(!(o1 instanceof String)||!(o2 instanceof String))throw new RuntimeException("传入元素非字符串");String str1=(String)o1;String str2=(String)o2;int length=str1.length()-str2.length();if(length==0){return str1pareTo(str2);}return length;}
}
class TreeSetTest
{public static void main(String[] args) {//TreeSet ts = new TreeSet();TreeSet ts = new TreeSet(new MyCompare());ts.add("abcd");ts.add("bsx");ts.add("abcc");ts.add("bceddd");ts.add("db");for(Iterator it = ts.iterator();it.hasNext();){System.out.());}}
}
运行图:
//泛型类的使用,该类的出现时解决在多态的情况下出现的安全性问题
package icclass;class Person
{}
class Worker extends Person
{}
class Student extends Person
{}
class Teacher extends Person
{}
//jdk1.5以前的Call写法
/*
class Call
{private Person p=null;public void setPerson(Person p){this.p=p;}public Person getPerson(){return p;}
}
*/
//现在的写法
class Call<E>//自定义一个占位符来代替不能确定的引用数据类型,因此也不用抽象出Person了,如果只是为了使用多态而抽取出来的话也不负责继承的原则
{private E e;public void setPerson(E e){this.e=e;}public E getPerson(){return e;}
}
class GenericClass
{public static void main(String[] args) {//泛型前的写法,问题多,而且代码复制冗余/*Call c = new Call();//c.setPerson(new Worker());//如果该句写成如下所示,在编译时通过,在运行时会报类型转换异常,这就是使用父类多态的缺点,需要进行大量的判断等来进行传入的参数的约束//同时即便如此,那么也只能在运行时才能看到问题所在,加大了解决问题的难度。c.setPerson(new Student());Worker w = (Person();*///使用泛型的写法Call<Student> c = new Call<Student>();//c.setPerson(new Student());//如果该句写成如下所示,在编译时期就会报错c.setPerson(new Worker());Student s = c.getPerson();//此处不需要再使用强制转化,代码更简洁}
}
//泛型方法的测试
//泛型类在确定了引用数据类型时就固定了,有时候不灵活
package icfunction;
class Demo<T>
{public void show(T t){System.out.println("show:"+t);}public void print(T t){System.out.println("print:"+t);}public <T> void function(T t){System.out.println("泛型方法:"+t);}
}
class GenericFunction
{public static void main(String[] args) {Demo<String> d = new Demo<String>();d.show("helong");d.print("ldy");//d.show(2);//如果此时想打印Integer类型的,那么只能重新定义一个Demo对象<Integer>//这就很麻烦了,因此我们使用泛型方法来解决d.function("helong");d.function(23);d.function(true);//可以看出,泛型方法更加灵活,但是由于泛型方法可以传入各种引用类型数据,//因此即便在方法内有强转等操作且传入参数错误,在编译时也不会再报错。//这就违反了泛型出现的目的:作为一种安全机制,因此只有在确认不会有安全//问题的情况下再使用泛型方法。}
}
运行图:
//泛型测试
//泛型:jdk1.5的新特性,一种类型安全机制。
//语法格式:通过<>定义引用数据类型
//使用泛型后,原本使用集合都会出现的注意也消失了,那是因为本身那个注意就是提醒
//程序员注意安全问题的。
package icdemo;
import java.util.*;
class GenericDemo
{public static void main(String[] args) {//假定我们向其中添加的都是字符串//ArrayList al = new ArrayList();ArrayList<String> al = new ArrayList<String>();al.add("helong1");al.add("helong12");al.add("helong123");//al.add(4);//集合中本是不能添加基本数据类型的,但是在jdk1.5之后有了自动装箱拆箱的特性,这句相当于al.add(new Integer(4));//此句编译时没问题,但是运行时报错,类型转换异常,Integer无法转换成String,这就有了安全性问题//原因在于本身集合对自己内部的元素没有限制,任意类型都能传进来。泛型用于解决这个问题。//for(Iterator it = al.iterator();it.hasNext();)//同样的在迭代器位置也可以使用泛型来指明迭代器中的是String类型,可以避免强制转换for(Iterator<String> it=al.iterator();it.hasNext();){//String temp=(();String temp();//无需强制转换System.out.println(temp+":"+temp.length());}}
}
运行图:
//泛型在比较器中的应用
//在TreeSet中存入字符串,主要条件长度,次要是字典序
package icdemo2;
import java.util.*;
class MyComparator implements Comparator<String>//为接口使用泛型,同样减少了强转的麻烦,如果传入非字符串则编译时期报错
{public int compare(String s1,String s2){//这个是正序,如果要求是反序呢?/*int temp=s1.length()-s2.length();if(temp==0)return s1pareTo(s2);return temp;*/int temp=s2.length()-s1.length();if(temp==0)return s2pareTo(s1);return temp;}
}
class GenericDemo2
{public static void main(String[] args) {//TreeSet<String> ts = new TreeSet<String>();TreeSet<String> ts = new TreeSet<String>(new MyComparator());ts.add("helong1");ts.add("helong12");ts.add("helong02");ts.add("helong323");ts.add("helong223");ts.add("helong2222");for(Iterator<String> it=ts.iterator();it.hasNext();){String temp();System.out.println(temp+":"+temp.length());}}
}
运行图:
/*
泛型限定:--向上限定:<? extends E> 可以接收E和E的子类对象;--向下限定:<? super E>可以接收E和E的父类对象;两种实现方法接收任意类型的写法:--public void show(ArrayList<?> al)--public <T> void show(ArrayList<T> al)
这两种写法都可以接收Person,Student,Demo泛型的ArrayList对象
但是在编译期间同样可以接收别的类型的对象而不报错,而是在运行
期间报错,这就违反了泛型的初衷--一种类型安全机制。
但是我们又不能如下这样写方法:
public void show(ArrayList<Person> al)
因为我们需要处理的不是只有Person,而是其所有子类,因为我们操作的是
这个体系的公有方法,因此我们理所因当的能处理这个体系的所有类,而不是
其中一个,这也是处于扩展性的角度。达到类似于多态的效果。
因此我们需要使用泛型限定:
不再是指定一个类型,而是将泛型限定在一个区间内
第一种:向上限定,指定最父类,那么我们就能传入这个父类和其所有子类
第二种:向下限定,指定最子类,那么我们就能传入这个子类和其所有父类泛型限定,向上限定较为常用,向下不常用,但是在API中时常见的,因此需要了解。
*/
package icdemo3;
import java.util.*;
class Other
{
}
class Person
{private String name;Person(String name){this.name=name;}public String getName(){return name;}
}
class Student extends Person
{Student(String name){super(name);}
}
class Demo extends Student
{Demo(String name){super(name);}
}
class GenericDemo3
{public static void show1(ArrayList<? extends Person> al){for(Iterator it = al.iterator();it.hasNext();){Person p = (();System.out.Name());}}public static <T> void show2(ArrayList<T> al){for(Iterator it = al.iterator();it.hasNext();){Person p = (();System.out.Name());}}public static void main(String[] args) {ArrayList<Person> al1=new ArrayList<Person>();ArrayList<Student> al2=new ArrayList<Student>();ArrayList<Demo> al3=new ArrayList<Demo>();al1.add(new Person("p1"));al1.add(new Person("p2"));al1.add(new Person("p3"));al2.add(new Student("s1"));al2.add(new Student("s2"));al2.add(new Student("s3"));al3.add(new Demo("d1"));al3.add(new Demo("d2"));al3.add(new Demo("d3"));show1(al1);show1(al2);show1(al3);show2(al1);show2(al2);show2(al3);//在编译期间不报错,而是运行时报错,因为Other类无法转为Person类//使用泛型限定后,该语句在编译时报错,因为Other无法转为Person或其子类//这就是泛型限定的好处,使得方法可以处理一定区间的集合范围,而不再是一个或者所有//ArrayList<Other> al4=new ArrayList<Other>();//al4.add(new Other());//show1(al4);//show2(al4);}
}
运行图:
//向下限定的用处
//TreeSet(Comparator<? super E> comparator)
package icdemo4;
import java.util.*;
class Person
{private String name;Person(String name){this.name=name;}public String getName(){return name;}
}
class Student extends Person
{Student(String name){super(name);}
}
class Worker extends Person
{Worker(String name){super(name);}
}class PerComp implements Comparator<Person>
{public int compare(Person p1,Person p2){Name()Name());}
}/*
//这种比较器的写法很麻烦,因为只要我们多一个Person的子类,就要多写一个比较器
//而这时完全没必要的,因为我们的函数体基本一致,因此我们应该提高扩展性,
//这时我们可以查阅API发现,在TreeSet构造函数那里的比较器参数是这样的Comparator<? super E> comparator
//这表示我们传递一个处理集合中存放类型E的比较器进去,然后它实际可以处理的是E和E的子类,因此我们
//应该传递Person进去
//当然扩展性增加了,局限性就来了,这样的比较器类中就只能操作Person的方法;
class StuComp implements Comparator<Student>
{public int compare(Student p1,Student p2){Name()Name());}
}
class WorComp implements Comparator<Worker>
{public int compare(Worker p1,Worker p2){Name()Name());}
}
*/
class GenericDemo4
{public static void main(String[] args) {TreeSet<Worker> ts = new TreeSet<Worker>(new PerComp());//比较器处理的集合中对象为Person,但是也能处理Person的子类ts.add(new Worker("p1"));ts.add(new Worker("p3"));ts.add(new Worker("p2"));for(Iterator<Worker> it=ts.iterator();it.hasNext();){System.out.().getName());}TreeSet<Student> ts1 = new TreeSet<Student>(new PerComp());ts1.add(new Student("s--1"));ts1.add(new Student("s--3"));ts1.add(new Student("s--2"));for(Iterator<Student> it=ts1.iterator();it.hasNext();){System.out.().getName());}}
}
运行图:
//测试Map的常用方法
package com.helong.mapdemo;
import java.util.*;
class MapDemo
{public static void main(String[] args) {Map<String,String> map=new HashMap<String,String>();map.put("01","ldy1");map.put("02","ldy2");map.put("03","ldy3");sop("put:"+map.put("04","ldy4"));//添加的特点,当key值已经存在时,会使用新的value代替旧的value,并返回旧的value。sop("put:"+map.put("04","ldy44"));sop("put:"+map.put("04","ldy444"));//删除ve("01"));ve("010"));//返回ve(1));//返回null,且并未报错//判断containsKey,containsValue,isEmptysop("是否包含key:"ainsKey("02"));sop("是否包含key:"ainsKey(1));sop("是否包含Value:"ainsValue("ldy4"));sop("是否包含Value:"ainsValue(4));sop("map是否为空:"+map.isEmpty());//获取getsop("get:"("01"));sop("get:"(1));sop("get:"("02"));//获取的特例,当添加的键值对中,值为null时map.put("05",null);sop("get:"("05"));//虽然返回了null,但是这不是说不存在值,而是值本身就是null}private static void sop(Object obj){System.out.println(obj);}
}
运行图: interface Map
{public static interface Entry{public abstract Object getKey();public abstract Object getValue();. .}
}
class HashMap implements Map
{class Inter implements Map.Entry{public Object getKey(){....}public Object getValue(){....}..}
}
/*
map取出值的两种方式:1.KeySet:将map中所有的键取出来放到一个Set中,然后使用迭代器来遍历Set取到每一个键,再通过map的get得到每个值。2.EntrySet:将map中的所有的映射关系放到一个Set中,使用迭代器遍历这些关系(Map.Entry),通过Entry的getKey和getValue方法获取键值。
*/
package com.helong.mapdemo2;
import java.util.*;
class MapDemo2
{public static void main(String[] args) {Map<String,String> map=new HashMap<String,String>();map.put("05","ldy5");map.put("02","ldy2");map.put("03","ldy3");map.put("01","ldy1");map.put("04","ldy4");for(Iterator<String> it = (map.keySet()).iterator();it.hasNext();)//使用迭代器获取到Set中的元素,并通过next方法遍历这些元素,同时通过Map的get方法取到Value。{System.out.(it.next()));}for(Iterator<Map.Entry<String,String>> it = Set().iterator();it.hasNext();)//entrySet方法返回的是一个存储Map.Entry<String,String>的Set集合,我们遍历集合取到每一个Map.Entry元素,并调用//该元素的getKey和getValue方法来获取键值。该类型的实现是Map接口的内部接口类型,且为公有静态的,外界可以直接使用{Map.Entry me = it.next();System.out.Key()+":"Value());}}
}
运行图 /*
每一个学生都有其归属地
学生:Student
归属地:String
注意:姓名和年龄一致视为同一个学生
保证学生唯一性思路:
1.描述学生
2.定义map,学生为键,归属地为值
3.遍历map元素如果一个类会产生大量的对象,那么该类可能存到集合中,那么该类就应该为了
能存入各个集合中而进行一些改动,例如实现hashCode,equals方法,为了存入hash表
具有可比性,也叫具有自然顺序,为了存入二叉树中等
*/
package com.helong.maptest;
import java.util.*;
class Student implements Comparable<Student>
{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+"t年龄:"+age;}public int hashCode(){return this.name.hashCode()+age*33;}public boolean equals(Object obj){if(!(obj instanceof Student))throw new RuntimeException("对象非学生类");Student temp=(Student)obj;return this.age=Age()&&this.name=Name();}public int compareTo(Student s)//使得学生类具有可比性,规则是主要条件为年龄,次要条件为姓名{//从小到大,按照年龄int temp=Age();System.out.println(this+"......"+s+"......."+temp);if(temp==0)return this.Name());return temp;}}
class MyComp implements Comparator<Student>
{public int compare(Student s1,Student s2){int tempName()Name());System.out.println(s1+"......"+s2+"......."+temp);if(temp==0)Age()-s2.getAge();return temp;}
}
class MapTest
{public static void main(String[] args) {//Map<Student,String> map=new HashMap<Student,String>();//数据存入hash表中,是无序的//Map<Student,String> map=new TreeMap<Student,String>();//经测试,成功的对元素进行了自然顺序的排序//新的需求,按照学生的姓名排序,我们不能随意修改学生类,因此可以使用比较器来完成Map<Student,String> map=new TreeMap<Student,String>(/*new MyComp()*/);map.put(new Student("abb",22),"北京");//为什么只存入一个元素时,也会调用两次比较器的compare方法呢?而在TreeSet中存入一个元素时会调用一次compare方法//map.put(new Student("bbb",21),"上海");/*map.put(new Student("小明",23),"深圳");map.put(new Student("何龙",22),"深圳");map.put(new Student("何小龙",20),"北京");map.put(new Student("何龙",22),"河北");map.put(new Student("刘冬园",22),"上海");map.put(new Student("小明",23),"深圳");map.put(new Student("何龙",27),"深圳");map.put(new Student("何小龙",22),"北京");*///使用两种方式遍历//keySetfor(Iterator<Student> it=map.keySet().iterator();it.hasNext();){Student s();System.out.println("keySet:t"+s+"t归属地:"(s));}/*//entrySetSystem.out.println("========================================================");for(Iterator<Map.Entry<Student,String>> itSet().iterator();it.hasNext();){Map.Entry me();System.out.println("entrySet:t"Key()+"t归属地:"Value());}*/}
}
运行图:
/*
题目:统计字符串中每个字母出现的次数,并打印输出
输出格式:a(1),b(3)....
思路:
我们可以看出字母和数字间有这映射关系,根据这种需求可以使用Map
我们又发现最后的打印输出格式最好是按字母顺序来的,因此我们使用TreeMap
而不是HashMap
步骤:
"dafjeljaflaefaeg"
1.转换成字符数组
2.遍历数组,将字母放到集合中比较
3.如果没有一样的,那么就添加,值为1
4.如果有一样的,那么先取出值,加1,再存入(如果键已经存在了,那么存储会用新的值代替旧的值)
5.遍历完毕
6.使用entrySet方式遍历map中的映射关系
7.打印key和value
*/
package aptest2;
import java.util.*;
class MapTest2
{public static void main(String[] args) {TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();//不能是char和int,需要引用数据类型char arr[]="dafj12eljafla56efaeg,,,qwea【【sdzx】】c".toCharArray();System.out.println("元字符串:dafj12eljafla56efaeg,,,qwea【【sdzx】】c");for(int i=0;i<arr.length;i++){//如果不是字母,直接跳过if(!((arr[i]>='a'&&arr[i]<='z')||(arr[i]>='A'&&arr[i]<='Z')))continue;Integer temp(arr[i]);//代码优化,put的代码重复了/*if(temp==null)//当前Map中还没有键为arr[i]的键值对,则添加键值对{tm.put(arr[i],1);}else//当前集合已经存在键为arr[i]的键值对,也是添加,只不过是将值+1后再添加进去//Integer+1是可以运算的,是JDK新特性:自动拆箱,自动装箱//使用基本类型的包装类的时候会有自动装箱,拆箱。{tm.put(arr[i],temp+1);}*///这样写,put只用写一遍if(temp==null)temp=1;else temp+=1;tm.put(arr[i],temp);}System.out.print("统计结果:");for(Iterator<Map.Entry<Character,Integer>> itSet().iterator();it.hasNext();){Map.Entry me();if(it.hasNext())System.out.Key()+"("Value()+")"+",");elseSystem.out.Key()+"("Value()+")");}}
}
运行图: /*
Map扩展:
假如我们要保存的信息格式是:"预热班" "何龙","01" "预热班" "冬园","02" "就业班" "小洪","01" "就业班" "小明","02"
我们发现数据间是有映射关系的,那么应该采用Map存储,但是这个问题中不止一个映射关系
1.班级和学生的映射关系
2.学号和学生的映射关系还有一个问题:一个班级与学生的映射关系中,很合理的是班级应该作为键,学生为值,但是同一个班级有很多学生,如果按照原先的存储方式,前面的学生会被覆盖掉,最终只保存了一个学生,这是不符合要求的,因此我们考虑将班级与学生集合映射到一起,也就是班级字符串为key,学生map为value。
*/
package com.helong.maptest3;
import java.util.*;
class MapTest3
{public static void main(String[] args) {HashMap<String,HashMap<String,String>> school = new HashMap<String,HashMap<String,String>>();HashMap<String,String> yure=new HashMap<String,String>();HashMap<String,String> jiuye=new HashMap<String,String>();school.put("预热班",yure);school.put("就业班",jiuye);yure.put("01","何龙");yure.put("02","冬园");jiuye.put("01","小洪");jiuye.put("02","小明");printStudentInfo(school,"预热班");printStudentInfo(school,"就业班");printStudentInfo(school);}//打印学校中某个班的全部学员信息private static void printStudentInfo(HashMap<String,HashMap<String,String>> school,String roomName){sop(roomName+"学员:");HashMap<String,String> room(roomName);for(Iterator<Map.Entry<String,String>> itSet().iterator();it.hasNext();){Map.Entry me();Key()+":"Value());}}//打印学校中所有学员的信息private static void printStudentInfo(HashMap<String,HashMap<String,String>> school){sop("学校所有学员信息:"); /*//这种方式比较复杂,而且没有体现代码复用,其实我们可以获取学校中的教室名,然后调用printStudentInfo(school,roomName)来解决for(Iterator<Map.Entry<String,HashMap<String,String>>> itSet().iterator();it.hasNext();){for(Iterator<Map.Entry<String,String>> iit().getValue().entrySet().iterator();iit.hasNext();){Map.Entry me();Key()+":"Value());}} *///下面这种方法代码简洁,充分体现代码复用的原则for(Iterator<String> it=school.keySet().iterator();it.hasNext();){printStudentInfo(());}}private static void sop(Object obj){System.out.println(obj);}
}
//还是MapTest3的例子,但是在实际开发中情况略有不同,我们不会让学号与姓名一一对应来存储
//而是将其封装成对象来存储
package com.helong.maptest4;
import java.util.*;
class Student
{private String id;private String name;Student(String id,String name){this.id=id;this.name=name;}public String toString(){return id+"----"+name;}
}
class MapTest4
{public static void main(String[] args) {//学校与班级HashMap<String,ArrayList<Student>> school=new HashMap<String,ArrayList<Student>>();ArrayList<Student> yure=new ArrayList<Student>();ArrayList<Student> jiuye=new ArrayList<Student>();school.put("预热班",yure);school.put("就业班",jiuye);yure.add(new Student("01","何龙"));yure.add(new Student("02","冬园"));jiuye.add(new Student("01","何花"));jiuye.add(new Student("02","何马"));for(Iterator<Map.Entry<String,ArrayList<Student>>> itSet().iterator();it.hasNext();){Map.Entry<String,ArrayList<Student>> me();ArrayList<Student> alValue();for(Iterator<Student> iit=al.iterator();iit.hasNext();){System.out.());}}}
}
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
本文发布于:2024-01-27 20:07:46,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17063572642366.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |