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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 刘源 中级黑马   /  2012-8-1 09:21  /  1957 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 刘源 于 2012-8-1 21:58 编辑

       谁能够总结下,对对象进行比较排序的的步骤啊,除了用到实现了Comparable接口中的compareTo方法,还有其他的方法吗。
最好将方法和适应的集合一起写下来。感觉学得凌乱了,又要复写equals(),又要复写hasCode()。还有这些方法的复写有先后顺序吗?



问题已经解决”。

4 个回复

倒序浏览
本帖最后由 余清兰 于 2012-8-1 09:35 编辑

你说的这两个问题涉及到的是Set集合中的两个子类
Set集合里的元素是无序(存入和取出的顺序不一定一致),元素不可以重复。
Set里有两个常用的子类,一个是HashSet底层数据结构是哈希表,当哈希值相同时,会比较是不是同一个对象,如果对象也相同,就是重复元素,就不会存入HashSet集合中。只要看到底层数据结构是Hash表的,就一定要覆写HashCode()和equals()这两个方法。
HashSet是如何保证元素唯一性的?
是通过元素的两个方法,hashcode和equals来完成。如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashcode值不同,就不会调用equals。
注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。(ArrayList只依赖equals方法)
import java.util.*;
class Person
{
        private String name;
        private int age;
        Person(String name,int age)
        {
                this.name = name;
                this.age = age;
        }
        public boolean equals(Object obj)
        {
                if(!(obj instanceof Person))
                        return false;
                Person p = (Person)obj;
                return this.name.equals(p.name) && this.age == p.age;
        }
        public int hashCode()
        {
                return name.hashCode()+age;
        }
        public String getName()
        {
                return name;
        }
        public int getAge()
        {
                return age;
        }
}
class HashSetTest
{
        public static void main(String[] args)
        {
                HashSet hs = new HashSet();
                hs.add(new Person("java01",11));
                hs.add(new Person("java02",12));
                hs.add(new Person("java03",13));
                hs.add(new Person("java03",13));
                hs.add(new Person("java04",14));
                Iterator it = hs.iterator();
                while (it.hasNext())
                {
                        Person p = (Person)it.next();
                        System.out.println(p.getName()+"..."+p.getAge());
                }
        }
}

而TreeSet:可以对set集合中的元素进行排序(ascii码表)。
TreeSet底层数据结构是二叉树,保证元素唯一性的依据:compareTo方法return 0
二叉树:小的往左边放,大的往右边放,比较的元素多了会自动折中。这样就能减少比较的次数,提高效率。取的时候默认顺序是由小到大的顺序取。
TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现comparable接口,覆盖compareTo方法,这种方式也称为元素的自然顺序,或者叫做默认顺序(元素一定义完就具备比较性)。
TreeSet排序的第二种方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。即是定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。定义一个类,实现Comparator接口,覆盖compare方法。
当两种排序都存在时,以比较器为主。

需求:将自定义对象存入TreeSet集合中,并按年龄排序。
记住:排序时,当主要条件相同时,一定要判断一下次要条件。
import java.util.*;
class TreeSetTest
{
        public static void main(String[] args)
        {
                TreeSet ts = new TreeSet();
                ts.add(new Student("lisi01",27));
                ts.add(new Student("lisi02",21));
                ts.add(new Student("lisi03",21));
                ts.add(new Student("lisi04",13));

                Iterator it = ts.iterator();
                while(it.hasNext())
                {
                        Student s = (Student)it.next();
                        System.out.println(s.getName()+"..."+s.getAge());
                }
        }
}
class Student implements Comparable//该接口强制让学生具备比较性
{
        private String name;
        private int age;

        public int compareTo(Object obj)
        {
                if(!(obj instanceof Student))
                        throw new RuntimeException("不是Student类对象");
                Student s = (Student)obj;
                if(this.age>s.age)
                        return 1;
                if(this.age==s.age)
                        return this.name.compareTo(s.name);
                return -1;
        }
        Student(String name,int age)
        {
                this.name = name;
                this.age = age;
        }
        public String getName()
        {
                return name;
        }
        public int getAge()
        {
                return age;
        }
}

例:按字符串的长度排序
import java.util.*;
class TreeSet2
{
        public static void main(String[] args)
        {
                TreeSet ts = new TreeSet(new MyComparator());
                ts.add("abc");
                ts.add("cd");
                ts.add("sa");
                ts.add("dwtrh");
                Iterator it = ts.iterator();
                while(it.hasNext())
                {

                        System.out.println(it.next());
                }
        }
}
class MyComparator implements Comparator
{
        public int compare(Object o1,Object o2)
        {
                String s1 =(String)o1;
                String s2 =(String)o2;

                int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
                if(num==0)
                        return s1.compareTo(s2);

                return num;
        }
}

评分

参与人数 1技术分 +1 收起 理由
杨志 + 1 很给力!

查看全部评分

回复 使用道具 举报
除了实现comparable接口,覆盖compareTo方法还可以自己定义比较器Comparator,覆盖compare方法。
就拿一个字符串数组长度排序来说,
如果把字符串放到list中,就可以用Collections工具类的sort方法。这个sort()方法也可以接收比较器Comparator。
  1. public class Sadf {
  2.         public static void main(String[]args)
  3.         {
  4.                 sortDemo();
  5.         }
  6.         public static void sop(Object obj)
  7.         {
  8.                 System.out.println(obj);
  9.         }

  10.         public static void sortDemo()
  11.         {
  12.                 List<String> ss=new ArrayList<String>();
  13.         //Set<String> ss=new TreeSet<String>(new sortComparator());

  14.                 ss.add("abc");
  15.                 ss.add("z");
  16.                 ss.add("tbceet");
  17.                 ss.add("abc");
  18.                 sop(ss);
  19.                 Collections.sort(ss, new sortComparator());
  20.                 sop(ss);
  21.         }
  22. }
  23. class sortComparator implements Comparator<String>
  24.         {
  25.                 public int compare(String s1,String s2)
  26.                 {
  27.                         if (s1.length()>s2.length())
  28.                         return 1;
  29.                         if (s1.length()<s2.length())
  30.                         return -1;
  31.        
  32.                                 return s1.compareTo(s2);
  33.                        
  34.                 }
  35.         }
复制代码
当然也可以用set,只不过存入的元素不能重复,直接Set<String> ss=new TreeSet<String>(new sortComparator());
元素进入集合后自动排序了

评分

参与人数 1技术分 +1 收起 理由
杨志 + 1

查看全部评分

回复 使用道具 举报
在C#中有三个关于比较对象大小的接口:分别是IComparable、IComparable和IComparer。
1, IComparable和IComparable是类本身实现的在实例之间比较大小的行为定义;
2, IComparer是定义在被比较类之外的专门比较两个T类型对象大小的行为;
3, 另外还有一个用于比较的委托定义Comparison可以让我们用拉姆达表达式或者匿名委托或方法更方便的排序。
下面介绍简单介绍IComparable接口
指定IComparer  类的对象方法实现对对象进行比较排序:
1,新定义一个类:A,这个类实现了泛型接口:IComparer<Product>;
2,然后在ProductSample.Sort(new A());语句写一个比较器对象;
3,该方法不如直接实现ICompareable接口简洁。
回复 使用道具 举报
问题已经解决
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马