由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,哈哈这篇其实也还是基础,惊不惊喜意不意外 ̄▽ ̄ 写文真的好累,懒得写了。。

温馨提醒:建议从(上)开始看哦~

 目 录

浅入深出之Java集合框架(上)

浅入深出之Java集合框架(中)  

浅入深出之Java集合框架(下)

Java集合框架编程练习小程序——扑克牌小游戏


前 言

在<浅入深出之Java集合框架(中) >中介绍了Map接口的基本操作。使用的示例是在<浅入深出之Java集合框架(上)>中的模拟学生选课的小程序,不清楚的朋友可以先去阅读<浅入深出之Java集合框架(上)>。

在本篇中我们将解决如下问题:

  • 在课程序列中,如何判断是否包含某门或者某几门课程?

  • 如果课程序列包含某门课程,如何判断该课程的索引位置?

  • 在学生映射表中,如何判断是否包含某个学生id?

  • 又该如何判断是否包含某个学生对象?

  • 如果把课程或者学生对象,按照课程名称或者学生姓名排序又该怎么办?按照ID排序呢?

问题看起来很多很复杂,其实主要就是两个部分:如何判断集合中是否包含某个元素如何把有序集合按照指定的规则进行排序


一、集合中contains方法的应用

对于第一个问题,集合提供了一个叫做contains的方法,这个方法就是用来判断该集合是否包含某个元素,对于contains方法我们分别从List、Set、Map集合来看看它的使用方法和注意事项。

1)List 中contains()方法——判断List中课程中是否存在

 首先我们来写一个测试方法来用contains方法来判断List中课程是否存在:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

 1 /* 2  * 测试List的contains方法 3  */ 4     public void testListContains(){ 5         //取得备选课程序列的第0个元素 6         Course cr=this.CoresesToSelect.get(0); 7         System.out.println("取得课程:" +cr.getId()+","+cr.getName()); 8         System.out.println("备选课程中是否包含课程:"+cr.getName()+","+this.CoresesToSelect.contains(cr)); 9         //创建一个新的课程对象,它的id和name和cr一样10         Course cr2=new Course(cr.getId(),cr.getName());11         System.out.println("备选课程中是否包含课程:"+cr2.getName()+","+this.CoresesToSelect.contains(cr2));12         //通过indexOf方法来取的某元素的索引位置13         if(CoresesToSelect.contains(cr2)){14             System.out.println("课程:"+cr2.getName()+"的索引位置为:"+CoresesToSelect.indexOf(cr2));15 16         }17     }

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

运行结果:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

结果分析:

从运行结果中可以看出第一个“数据结构”课程调用contains方法返回时true,而第二个“数据结构”课程调用contains方法返回时false。为什么同样都是名为“数据结构”的课程为什么会有两种截然不同的结果?

第一个“数据结构”课程是从CoresesToSelect集合中取出来的,所以理所当然地CoresesToSelect集合中包含它,调用contains方法返回时true;而第二个“数据结构”课程是new(新创建)的课程,系统开辟了另一个内存空间,虽然令它的名称和第一个“数据结构”相同,但是对于系统来说是两个不同的对象。contains方法默认是比较引用对象内存地址的(哈希码),那么如何才能使用相同名称的课程来判断List中是否包含该课程呢?

这里我们需要来深入了解contains方法的原理,来帮助我们理解和使用contains方法。如下图所示:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

方法中的所有类都是继承于Object类,而在Object类中有一个equals()方法,它是用来比较两个对象是否相等的,关于equals()方法的详解在我的其他博文中,链接:http://www.cnblogs.com/hysum/p/7100874.html

然后我们来看看contains方法的内部原理是怎么样的。

如上图所示,contains方法其实通过遍历集合中的每个对象的equals方法来比较两个对象是否相等,如果相等返回true ,否则返回false。而equals()默认是比较两个对象的引用是否相等,如果我们要通过contains方法来比较两个对象的值是否相等来判断集合中是否含有一个对象,则必须重写该对象的equals()方法。

下面以比较两个课程对象的名称是否一样来重写Course类equals()方法,如:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

 1 public void equals (Object obj) 2 { 3   if(this == obj)  // 指向同一个内存快 必然是相同的 4      returned true;  //为什么contains(course2) 返回的是false 原因就在在这里 只是比较了一下 引用的值是否相同 没有进一步的比较 内存块中的值 下就是对这里记性了改写 5   if (obj == null)  // 如果obj为空 就直接没有戏了 6      return false; 7   if(! (obj instanceof Course))  //如果两者的不属于同一类型则 也直接没戏了 8     return false; 9   //经过以上的这么多的比较 终于可以判断二者的值是不是相同了10   //首相要把objet型的obj转成 Course11   Course course = (Course)  obj;12   if( this.name == null )13   {14      if(course.name == null )15         return true;16      else return false;17    }18    else19    {20      if(this.name.equals(course.name)) return true;21      else return false;22    )23    //如果还有别的属性接着写24 }

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

重写完Course类的equals()方法后,我们重写运行一下程序,结果如下:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

可以看到contains方法可以根据课程名称来判断是否包含该课程了。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

这里的indexOf()方法与lastIndexOf()方法实现原理和contains方法相似:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

1、遍历调用每个元素的equals()方法,如果返回true则将次元素的索引返回;

2、如果有多个相同元素,则只返回第一个元素的索引;

3、lastIndexOf()方法则从最后一个元素开始遍历;

2)Set中contains()方法——判断Set中课程是否存在

 首先我们也来写一个测试方法来用contains方法来判断Set中课程是否存在:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

 1     /* 2      * 测试Set的contains方法 3      */ 4     public void testSetContains(){ 5         System.out.println("请输入学生已选的课程名称:"); 6         String cName=in.next(); 7         Course c=new Course(cName); 8         System.out.println("学生已选的课程是否包含课程:"+cName+","+stu.getCourses().contains(c)); 9 10     }

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

运行结果:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

这就奇怪了,我们不是已经重写了Course类的equals()方法吗?为什么在Set集合里调用contains方法还是返回false?

原来在HashSet里的contains方法和List里略有不同。它的原理如下图所示:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

Set.contains(E e)工作原理是先调用从Object继承而来的hashCode方法,然后再调用equals()方法,如果hashCode相同,才会调用equals方法,只有两者都返回true,contains方法 才返回true。jvm运行时,给每个对象分配唯一一个标志身份的标志hashcode。众类鼻祖Object的hashCode()方法在默认情况下,判断哈希码是不是相同。即如同equals默认情况下比较的是二者是不是同一个内存快。Set集的contains方法,内部就是先调用hashCode再调用equals()方法。很多情况要结合实际对hashCode进行改写。

这里给出我对hashCode的重写(系统自动生成):

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

1 public int hashCode() {2         final int prime = 31;3         int result = 1;4         result = prime * result + ((name == null) ? 0 : name.hashCode());5         return result;6     }

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

然后我们重写运行一下程序,结果如下:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

这里我总结一下List和Set中contains方法的注意事项

1.list 与 set 中contain()方法调用机制:

list 中的contain()方法是拿到list中的每个对象来调用Object类中的equals()方法;

Set  中的contain()方法是拿到list中的每个元素来先调用hashcode()方法来返回哈希码值,当哈希码的值相等时,再调用equals()方法,当比较的元素此时也相同时,才会返回true。因此调用Set中的contain()方法时,需要对hashcode()方法及equals()方法进行重写。

2. == 和equals()两种比较方法,在使用时要注意:

1)对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;

          如果作用于引用类型的变量,则比较的是所指向的对象的地址。

2)对于equals方法,注意:equals方法不能作用于基本数据类型的变量。

如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;诸如String、Date等类应该根据情况覆盖其父类或Object类中的equals()方法,否则默认的equals()方法功能与“==”相同。

3)Mapt中containsKey方法和containsValue方法——判断Map中是否包含指定的key和value

Map中通过containsKey()方法和containsValue()方法来判断键和值是否存在(已经重写Student类的Hashcode和equals方法,这里不再列出)

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

 1 /* 2      * 测试Map中,是否包含某个key值或者某个value值 3      */ 4     public void ContainsKeyOrValue(){ 5         //在Map中,用containsKey方法,来判断是否包含某个key值 6         System.out.println("请输入学生id:"); 7         String id =in.next(); 8         System.out.println("您输入的学生id为"+id+",Map中是否包含此id:"+this.students.containsKey(id)); 9         if(students.containsKey(id)){10             System.out.println("对应的学生姓名:"+students.get(id).getName());11 12         }13         //在Map中,用containsValue方法,来判断是否包含某个value值14         System.out.println("请输入学生姓名:");15         String name =in.next();16         Student st=new Student();17         st.setName(name);18         System.out.println("您输入的学生姓名为"+name+",Map中是否包含此姓名:"+this.students.containsValue(st));19         if(students.containsValue(st)){20             21             Set<Entry<String, Student>> entrySet =students.entrySet();22             for(Entry<String, Student> entry:entrySet){23                 if(entry.getValue().getName().equals(name)){24                     System.out.println("对应的学生的id:"+entry.getValue().getId());25                 }26 27             }28         }29 30     }

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

运行结果:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

注意:

1.Map 中对对象进行了 Key 标记,通过 get(Key)可以取得对应的对象。

2.Map 的containsValue()方法的参数是 Object 对象,因为Map 的 Value 值是对象元素。

3.Map 的containsKey()方法取得 Map 映射的 Key 值。

4.Map中的containsValue()方法原理跟HashSet的contains()相同,所以要重写Hashcode和equals方法。


二、Collections工具类

对于第二个问题,java集合框架还有一个成员就是Collections工具类,这个工具类提供了很多操作集合的方法,其中sort()方法是很常见的方法,它能对有序集合按照默认规则进行排序。接下来我们通过实例来看看Collections工具类是如何通过sort()对List进行排序的。

我写了四个测试方法来测试sort()方法,分别如下:

1)对Integer泛型的List进行排序

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

 1 /* 2      * 1.通过Collections.sort()方法,对Integer泛型的List进行排序 3      * 创建一个Integer泛型的List,插入十个100以内的不重复随机整数 4      * 调用Collections.sort()方法对其排序 5      */ 6     public void testSort1(){ 7         //创建一个Integer泛型的List,插入十个100以内的不重复随机整数 8         List<Integer> intList=new ArrayList<Integer>(); 9         int i=0;10         do{11             Random random=new Random();12             Integer n=random.nextInt(100);13             if(!intList.contains(n)){14                 intList.add(n);15                 System.out.println("成功添加整数:"+n);16                 i++;17             }18         }while(i<10);19         System.out.println("----------排序前-----------");20         for(Integer t:intList){21             System.out.print(t+"  ");22         }23         System.out.println();24         //调用Collections.sort()方法对其排序25     26         System.out.println("----------排序后-----------");27         Collections.sort(intList);28         for(Integer t:intList){29             System.out.print(t+"  ");30         }31     }

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

运行结果:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

这里我使用了Random类来获取随机数,Random类的出现,可以替代之前的Math.random方法

Random类有很多方法:nextByte、nextDouble、nextInt、nextDouble、nextBoolean、nextFloat、nextLong,获取各种类型的随机数但是没有nextShort和nextCharacter

并且对于nextInt并且支持传入一个int类型参数,作为随机数的取值范围。

常见用法:nextInt对于从某一个String类型的对象中,获取一个随机位的字符很有用,

例如String str = "sdfsfsfsdsafdf"; Random r = new Random();char c = str.charAt(r.nextInt(str.length));

2)对String泛型的List进行排序

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

 1 /* 2      *2.对String泛型的List进行排序 3      * 创建一个String泛型的List,添加三个乱序的String 4      * 调用Collections.sort()方法对其排序 5      */ 6     public void testSort2(){ 7         //创建一个String泛型的List,添加三个乱序的String 8         List<String> strList=new ArrayList<String>(); 9         String[] str={"egesg","eDSGvdxbrb","23235sdvfsd"};10         strList.addAll(Arrays.asList(str));11         System.out.println("----------排序前-----------");12         for(String s:strList){13             System.out.print(s+",");14         }15         System.out.println();16     //调用Collections.sort()方法对其排序17         System.out.println("----------排序后-----------");18         Collections.sort(strList);19         for(String s:strList){20             System.out.print(s+",");21         }22     }

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

运行结果:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

再写一个稍微复杂一点的例子:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

 1 /* 2      * 3      * 创建一个String泛型的List,往其中添加十条随机字符串 4      * 每条字符串的长度为10以内的随机整数 5      * 每条字符串的每个字符都为随机生成的字符,字符可以重复 6      * 每条随机字符串不可以重复 7      * 调用Collections.sort()方法对其排序 8      */ 9     public String getRandomString(int size) {10         StringBuilder str= new StringBuilder();//可变字符串11         Random random=new Random();12         //存放所包含字符62位13         String  container = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";14         for(int j=0;j<size;j++){15             str.append(container.charAt(random.nextInt(container.length()-1)));16         }17         return str.toString();18     }19     public void testSort3(){20     21         //创建一个String泛型的List22         List<String> strList=new ArrayList<String>();23         Random random=new Random();24         String str;25         for(int i=0;i<10;i++){//添加十条随机字符串26             do{27             int size=random.nextInt(10);//每条字符串的长度为10以内的随机整数28             str=getRandomString(size);29             }while(strList.contains(str)||str.length()==0);30             strList.add(str);31

作者: 云开的立夏

出处: http://www.cnblogs.com/hysum/>

关于作者:本人目前还在上学,小白一枚,希望能把学过的知识与大家分享,请多多赐教!

版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出 原文链接

大家写文都不容易,请尊重劳动成果~这里谢谢大家啦(*/ω\*) 如有问题, 可邮件(hysum626@162.com)咨询.

http://www.cnblogs.com/hysum/p/7141761.html

网友评论