java中collection框架应用示例:学生选课系统

java中集合框架概述


image.png
  • collection集合框架存储对象,有多个接口list,queue,set。他们对应的重要实现类分别是ArrayList,LinkedList,HashSet

定义类图

image.png

public class Course {

public String id;
public String name;
public Course(String id,String name){
    this.id=id;
    this.name=name;
}
public Course(){
}

}

public class Student {

public String id;
public String name;

public Set<Course> courses;

public Student(String id,String name){
    this.id=id;
    this.name=name;
    this.courses=new HashSet<Course>();
}

}

使用List接口


image.png
image.png

/*

  • 备选课程类
    */

public class ListTest {

public List courseToSelect;


/*
 * 用于存放备选课程的list
 */


public ListTest(){
    this.courseToSelect = new ArrayList();
}


/*
 * 用于往coursetoselect中添加备选课程
 */
public void testAdd(){
    //创建一个课程对象并通过调用add方法,添加到备选课程list中
    Course cr1= new Course("1","数据结构");
    courseToSelect.add(cr1);
    Course temp= (Course) courseToSelect.get(0);
    //System.out.println("添加了课程:"+temp.id+":"+temp.name);
    
    Course cr2 = new Course("2","c语言");
    courseToSelect.add(0, cr2);
    Course temp2=(Course)courseToSelect.get(0);
 //System.out.println("添加了课程:"+temp2.id+":"+temp2.name);
    courseToSelect.add(cr1);
    Course temp0= (Course) courseToSelect.get(2);
    //System.out.println("添加了课程:"+temp0.id+":"+temp0.name);
    
          //以下会抛出数组下标越界异常
           //Course cr3 = new Course("3","cdsfsf");
          //courseToSelect.add(4, cr3);
          Course[] course={new Course("3","离散数学"),new Course("4","汇编语言")};
    courseToSelect.addAll(Arrays.asList(course));
    Course temp3=(Course)courseToSelect.get(3);
    Course temp4=(Course)courseToSelect.get(4);
    
    //System.out.println("添加了两门课程:"+temp3.id+":"+
    //temp3.name+";"+temp4.id+":"+temp4.name);
    
    Course[] course2={new Course("5","高等数学"),new Course("6","大学英语")};
    courseToSelect.addAll(2, Arrays.asList(course2));
    Course temp5=(Course)courseToSelect.get(2);
    Course temp6=(Course)courseToSelect.get(3);
    
    //System.out.println("添加了两门课程:"+temp5.id+":"+
    //temp5.name+";"+temp6.id+":"+temp6.name);

}


/*
 * 取得List中的元素的方法
 */

public void testGet(){
    int size =courseToSelect.size();
    System.out.println("有如下课程待选:");
    for(int i=0;i<size;i++){
        Course cr = (Course) courseToSelect.get(i);
        System.out.println("课程:"+cr.id+cr.name);
    }
    
}

/*
 * 通过迭代器遍历List
 */

public void testIterator(){
    //通过集合的Iterator方法
    Iterator it = courseToSelect.iterator();
    System.out.println("有如下课程待选(通过迭代器访问):");
    while(it.hasNext()){
        Course cr =(Course)it.next();
        System.out.println("课程:"+cr.id+cr.name);
    }
    
}

/*
 * 通过foreach方法访问集合元素
 */
public void testForEach(){
    System.out.println("有如下课程待选(通过for each)):");
    for(Object obj:courseToSelect){
        //当元素被存入集合,其类型被忽略为object
        Course cr =(Course)obj;
        System.out.println("课程:"+cr.id+cr.name);
    }
}


/*
 * 修改list中的元素
 */
public void testModify(){
    courseToSelect.set(4, new Course("7","毛概"));
}

/*
 * 删除list中的元素
 */
public void testRemove(){
//  Course cr =(Course)courseToSelect.get(4);
//  System.out.println("我是课程"+":"+cr.name+" 我即将被删除");
    //System.out.println("即将删除4位置上的课程!");
    //courseToSelect.remove(4);
    
    
    System.out.println("即将删除4位置和5 位置上的课程!");
    Course[] courses ={(Course) courseToSelect.get(4),(Course) courseToSelect.get(5)};
    courseToSelect.removeAll(Arrays.asList(courses));
    System.out.println("成功珊瑚课程!");
    testForEach();
}


/*
 * 往list中添加一些奇怪的东西
 *
 */

// public void testType(){
// System.out.println("能否在list");
// courseToSelect.add("字符串");
// //不能,用泛型规定添加的元素类型
// }

public static void main(String[] args){
    ListTest lt=new ListTest();
    lt.testAdd();
    lt.testForEach();

}

}

应用泛型管理课程


image.png

public class TestGeneric {

/*
 * 带有泛型---course,的list类型属性
 */

public List<Course> courses;

public TestGeneric(){
    this.courses=new ArrayList<Course>();
    
}

/*
 * 测试添加
 */

public void testAdd(){
    Course cr1 =new Course("1","大学语文");
    courses.add(cr1);
    //courses.add("能否添加一些奇怪的东西呢???");//当然不能。编译期间检查,不是泛型规定的类型,报错
    //泛型集合中。不能添加 泛型规定的类型及其子类型以外的对象,否则会报错!
    Course cr2 = new Course("2","java basic");
    courses.add(cr2);
}

/*
 * 测试循环遍历
 */
public void testForEach(){
    for(Course cr:courses){
        System.out.println(cr.id+":"+cr.name);
    }
}

/*
 * 泛型集合可以添加泛型的子类型的对象实例
 */

public void testChild(){
    ChildCourse ccr = new ChildCourse();
    ccr.id="3";
    ccr.name="我是子类型的课程对象实例";
    courses.add(ccr);
}


/*
 * 泛型不能使用基本类型
 */
public void testBasicType(){
    List<Integer> list = new ArrayList<Integer>();
    //注意泛型中的限定类型不能使用基本类型,可以通过使用包装类
    list.add(1);
    System.out.println("基本类型必须使用包装类作为泛型!"+list.get(0));
}

public static void main(String[] args) {
    // TODO Auto-generated method stub
    TestGeneric tg=new TestGeneric();
    tg.testAdd();
    tg.testForEach();
    tg.testChild();
    tg.testForEach();
    tg.testBasicType();
}

}

public class ChildCourse extends Course {
}

使用set集合


image.png

image.png
public class SetTest {
public List<Course> courseToSelect;
public SetTest(){
        courseToSelect = new ArrayList<Course>();
}

public void testAdd(){
        //创建一个课程对象并通过调用add方法,添加到备选课程list中
        Course cr1= new Course("1","数据结构");
        courseToSelect.add(cr1);
        
        Course cr2 = new Course("2","c语言");
        courseToSelect.add(0, cr2);
        
        Course[] course={new Course("3","离散数学"),new Course("4","汇编语言")};
        courseToSelect.addAll(Arrays.asList(course));

        
        Course[] course2={new Course("5","高等数学"),new Course("6","大学英语")};
        courseToSelect.addAll(2, Arrays.asList(course2));

        
}

public void testForEach(){
    System.out.println("有如下课程待选(通过for each)):");
    for(Object obj:courseToSelect){//当元素被存入集合,其类型被忽略为object
        Course cr =(Course)obj;
        System.out.println("课程:"+cr.id+cr.name);
    }
}

public static void main(String[] args) {
    // TODO Auto-generated method stub
    SetTest st = new SetTest();
    st.testAdd();
    st.testForEach();
    
    Student student = new Student("1","Ming");
    System.out.println("欢迎学生: "+student.name+" 选课");
    //创建一个scanner对象接受从键盘输入的课程ID
    Scanner console = new Scanner(System.in);
    
    for(int i=0;i<3;i++){
        System.out.println("请输入课程ID");
        String courseId = console.next();
        for(Course cr :st.courseToSelect){
            if(cr.id.equals(courseId)){
                student.courses.add(cr);
                /*
                 * set中,添加某个对象,无论添加多少次
                 * 最终只保留一个该对象(的引用)
                 * 并且,保留的是第一次添加的那一个
                 */
                //student.courses.add(null);//可以添加空对象,但是没什么意义
        
        }
    }
}
    st.testForEachforSet(student);

}

public void testForEachforSet(Student student){
   //打印输出,学生所选的课程!
    System.out.println("共选择了:"+student.courses.size()+"门课程");
    for(Course cr:student.courses){
        System.out.println("选择了课程:"+cr.id+cr.name);
    }
}

}

使用map接口


  • map提供映射关系,以键值对存储。


    image.png
image.png

代码示例

public class MapTest {

/*
 * 用来承装学生类型对象
 */
public Map<String,Student>students;

/*
 * 在构造器中初始化student属性
 */

public MapTest(){
    this.students = new HashMap<String,Student>();
}

/*
 * 测试添加:输入学生id,判断是否被占用
 * 若未被占用。则输入学生姓名,创建新的学生对象,并且添加到students中
 */
public void testPut(){
    //创建一个scanner对象,用来获取输入的学生ID和姓名
    Scanner console = new Scanner(System.in);
    int i = 0;
    while(i<3){
        System.out.println("请输入学生ID");
        String ID =console.next();
        //判断该ID是否被占用
        Student st =students.get(ID);
        if(st==null){
            //提示输入学生姓名
            System.out.println("请输入学生姓名");
            String name = console.next();
            //创建一个新的学生对象
            Student newStudent = new Student(ID,name);
            //通过调用studnets的put方法,添加ID-学生映射
            students.put(ID, newStudent);
            System.out.println("成功添加学生:"+students.get(ID).name);
            i++;
        }else{
            System.out.println("该学生ID已被占用");
            continue;
        }
    }
}

/*
 * 测试map的keySet方法
 */
public void testKeySet(){
    //通过keyset方法。返回map中的所有“键”的set集合
    Set<String> keySet = students.keySet();
    //取得stuents的容量
    System.out.println("总共有:"+students.size()+"个学生");
    //遍历keyset,取得每一个键,在调用get方法取得每个键对应的value
    for(String stuId:keySet){
        Student st =students.get(stuId);
        if(st!=null){
            System.out.println("学生:"+st.name);
        }
    }
}

/*
 * 测试删除map中的映射
 */
public void testRemove(){
    //获取从键盘输入的待删除学生ID字符串
    Scanner console = new Scanner(System.in);
    while(true){
        //提示输入待删除的学生的ID
        System.out.println("请输入要删除的学生ID!");
        String ID =console.next();
        //判断该ID是都有对应的学生对象
        Student st =students.get(ID);
        if(st==null){
            //提示输入的ID并不存在
            System.out.println("该ID不存在");
            continue;
        }
        students.remove(ID);
        System.out.println("成功删除学生:"+st.name);
        break;
    }
}

/*
 * 通过entrySet方法来遍历Map
 */
public void testEntrySet(){
    //通过entrySet该方法,返回map中所有键值对
    Set<Entry<String,Student>> entrySet= students.entrySet();
    for(Entry<String,Student> entry:entrySet){
        System.out.println("取得键:"+entry.getKey());
        System.out.println("对应的值为"+entry.getValue().name);
    }
}

/*
 * 利用put方法修改map中的已有映射
 */
public void testModify(){
    //提示输入要修改的学生ID
    System.out.println("请输入要修改的学生ID:");
    //创建scanner对象,获取从键盘上输入的学生ID字符串
    Scanner console = new Scanner(System.in);
    while(true){
        String stuID= console.next();
        //从tsudnets中差好啊该学生ID对应的学生对象
        Student student= students.get(stuID);
        if(student ==null){
            System.out.println("该ID不存在!请重新输入!");
            continue;
        }
        //提示当前对应的学生对象的姓名
        System.out.println("当前该学生的ID:所对应的学生为"+student.name);
        //体术输入新的学生姓名,来修改已有的映射
        System.out.println("请输入新的学生姓名:");
        String name= console.next();
        Student newStudent = new Student(stuID,name);
        students.put(stuID, newStudent);
        System.out.println("修改成功!");
        break;
    }
}

public static void main(String[] args) {
    // TODO Auto-generated method stub
    MapTest mt = new MapTest();
    mt.testPut();
    mt.testKeySet();
    mt.testRemove();
    mt.testEntrySet();
    mt.testModify();
    mt.testEntrySet();
}

}

判断是否包含某元素


image.png

利用contains方法

  • 该方法从collection继承来
  • 下面测试list和set的contains方法

测试set的contains方法

public void testListContains(){

//取得备选课程序列的第0个元素
Course course = courseToSelect.get(0);
//打印输出courseToSelect是否包含course对象
System.out.println("取得课程:"+course.name);
System.out.println("备选课程中是否包含课程:"+course.name+","+courseToSelect.contains(course));
//包含返回true,不包含返回false
//创建一个新的课程对象,ID和名称,与course对象完全一样
Course course2 = new Course(course.id,course.name);
System.out.println("新创建课程:"+course2.name);
System.out.println("备选课程中是否包含课程"+course2.name+","+courseToSelect.contains(course2));//**这里是false**

}

  • 所有类都继承自object 有一个equals(Object obj)方法
  • contains(obj)方法实际是遍历其中每一个元素,调用每个元素的equals方法与参数obj比较,所有都不相同,才返回false
  • 通过重写equals方法可以实现通过contains是否包含名称为某个值的课程元素
    在Course类中重写equals方法

//Override

public boolean equals(Object obj){

    if(this==obj){
        return true;
    }
    if(obj==null)
        return false;
    if(!(obj instanceof Course))
        return false;
    Course course =(Course)obj;
    if(this.name==null){
        if(course.name==null)
            return true;
        else
            return false;
    }else{
        if(this.name.equals(course.name))
            return true;
        else
            return false;
    }
}

注:该equlas重写方法可以作为一个模板使用

这之后运行setTest
其中System.out.println("备选课程中是否包含课程"+course2.name+","+courseToSelect.contains(course2));//
得到的这里是true,说明equals方法重载成功。

  • object中还有一个方法:hashCode()返回该对象的哈希码的值

  • 当调用contains(obj)的时候,先调用每一个元素的hashcode(),相等再调用equals()。只有认为这两个方法返回的值都相等的时候,才认定hashset包含这个元素

    @Override
    public int hashCode() {

      final int prime = 31;
      int result = 1;
      result = prime * result + ((name == null) ? 0 : name.hashCode());
      return result;
    

    }
    @Override
    public boolean equals(Object obj) {

      if (this == obj)
          return true;
      if (obj == null)
          return false;
      if (!(obj instanceof Course))
          return false;
      Course other = (Course) obj;
      if (name == null) {
          if (other.name != null)
              return false;
      } else if (!name.equals(other.name))
          return false;
      return true;
    

    }

Ecilpse可以自动生成hashcode和equals方法。

判断元素的索引位置


//通过indexof方法来获取某元素的索引位置

    if(courseToSelect.contains(course2))
        System.out.println("课程:"+course2.name+"的索引位置为"+courseToSelect.indexOf(course2));
  • indexof(java)从0开始遍历,逐个进行equals(java)比较,若返回true,得到元素的索引位置。如果有多个重复元素,返回第一个元素的索引位置
  • lastIndexOf(java)方法与indexof相反,从最后开始遍历
  • 若没有找到该元素,这两个方法都返回-1

判断map中是否包含指定的key和value值


/*
 * 测试map中,是否包含某个key值或者某个value值
 */
public void testContainsKeyOrValue(){
    System.out.println("请输入要查询的学生ID");
    Scanner console = new Scanner(System.in);
    String id = console.next();
    //在map中,用containsKey()方法,来判断是否包含某个Key值
    System.out.println("您输入的学生ID为"+id+",在学生映射表中是否存在:"+students.containsKey(id));
    if(students.containsKey(id))
        System.out.println("对应的学生为:"+students.get(id).name);
    
    System.out.println("请输入要查询的学生姓名:");
    String name = console.next();
    //用containsValue()方法,来判断是否包含某个Value值
    if(students.containsValue(new Student(null,name)))
        System.out.println("在学生映射表中,确实包含学生:"+name);
    else{
        System.out.println("在学生映射表中不存在该学生");
    }
    
}

【注】这里的查询是否包含学生姓名的时候contain方法仍然调用了hashcode和equals方法,所以要在student类中重载两个方法

应用collection.sort()实现list排序


  • java.util.collections工具类,提供了许多静态方法,用来操作集合
  • 用collection.sort()实现list排序

/*

  • 将要完成:
  • 1.通过Collections.sort()方法,对Integer泛型的list进行排序
  • 2.对String泛型的List进行排序
  • 3.对其他类型泛型的list进行排序,以student为例
    */

public class CollectionsTest {

/*
 * 1.通过Collections.sort()方法,对Integer泛型的list进行排序
 * 创建一个Integer泛型的list,插入是个100以内不重复的随机数
 * 调用Collections.sort()方法排序
 */
public void testSort1(){
    List<Integer> integerList = new ArrayList<Integer>();
    //插入是个100以内不重复的随机数
    Random random = new Random();
    Integer k = null;
    for(int i=0;i<10;i++){
        do{
        k = random.nextInt(100);
        }while(integerList.contains(k));
    integerList.add(k);
    System.out.println("成功添加整数:"+k);
    }
    System.out.println("--------排序前-----------");
    for (Integer integer : integerList) {
        System.out.println("元素:"+integer);
    }
    Collections.sort(integerList);
    System.out.println("--------排序后-----------");
    for (Integer integer : integerList) {
        System.out.println("元素:"+integer);
    }
}

/*
 * 2.对String泛型的List进行排序
 * 创建String泛型的list,添加三个乱序的String
 * 调用sort方法,再次输出排序后的顺序
 */

public void testSort2(){
    List<String> stringList = new ArrayList<String>();
    stringList.add("microsoft");
    stringList.add("google");
    stringList.add("eldasdaf");
    System.out.println("--------排序前-----------");
    for (String string : stringList) {
        System.out.println("元素:"+string);
    }
    Collections.sort(stringList);
    System.out.println("--------排序后-----------");
    for (String string : stringList) {
        System.out.println("元素:"+string);
    }
}


/*
 * 3.对其他类型泛型的list进行排序,以student为例
 */
public void testSort3(){
    //....
    }
}

comparable与comparator接口

image.png
  • comparable默认比较规则,可比较的,实现改接口表示:这个类的示例可以bijou大小。可以进行自然排序。

public class Student implements Comparable<Student>{

@Override
public int compareTo(Student o) {
    // TODO Auto-generated method stub
    return this.id.compareTo(o.id);
}

public void testSort3(){

    List<Student> studentList = new ArrayList<Student>();
    Random random = new Random();
    studentList.add(new Student(random.nextInt(1000)+"","mike"));
    studentList.add(new Student(random.nextInt(1000)+"","xixo"));
    studentList.add(new Student(random.nextInt(1000)+"","Lan"));
    System.out.println("--------排序前-----------");
    for (Student student : studentList) {
        System.out.println("学生:"+student.id+":"+student.name);
    }
    Collections.sort(studentList);
    System.out.println("--------排序后-----------");
    for (Student student : studentList) {
        System.out.println("学生:"+student.id+":"+student.name);
    }
}
  • comparator 定义临时比较规则

public class StudentComparator implements Comparator<Student> {

@Override
public int compare(Student o1, Student o2) {
    // TODO Auto-generated method stub
    return o1.name.compareTo(o2.name);
}

}

public void testSort3(){

    List<Student> studentList = new ArrayList<Student>();
    Random random = new Random();
    studentList.add(new Student(random.nextInt(1000)+"","mike"));
    studentList.add(new Student(random.nextInt(1000)+"","xixo"));
    studentList.add(new Student(random.nextInt(1000)+"","Lan"));
    studentList.add(new Student(10000+"","beyonce"));
            //这里按照姓名排序
    Collections.sort(studentList,new StudentComparator());
    System.out.println("---------按照姓名排序后---------");
    for (Student student : studentList) {
        System.out.println("学生:"+student.id+":"+student.name);
    }
}

总结

image.png

所有类图

image.png

github地址:Elylicery
https://github.com/Elylicery/Code-Exercise/tree/master/imooc-collection-demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342