一、集合排序(方法一)
概念: java.lang.Comparable接口适用于一个类有自然顺序的时候。假定对象集合是同一类型,该接口允许把集合排序成自然顺序。该接口中的int compareTo( T obj )方法: 比较当前实例对象与对象obj,如果位于对象obj之前,返回负值;如果两个对象在排序中位置相同,则返回0;如果位于对象obj后面,则返回正值。
实现要点:让被放置到容器的对象类实现Comparable接口。由其中所实现的方法compareTo( )决定对象之间的排列顺序。
注意: TreeSet和TreeMap都是有排序功能的集合,而HashSet是没有排序功能的集合。
代码示例:(以TreeSet集合为例,让集合中的String对象与Employee对象按指定规则进行排序。)
Employee对象:(下面的MySort2有用到这个类)
public class Employee implements Comparable{ private String id; //id号 private String name; //名字 private int age; //年龄 private String department; //部门 static int no =1; //在Employee中自行编号 //构造函数 public Employee(String name, int age, String department) { this.id = "no."+(no++); //每次给的编号加一 this.name = name; this.age = age; this.department = department; } //构造函数(如果没有部门号,就设置为“no department”) public Employee(String name, int age) { this(name, age, "no department"); } //hash函数和equals函数 @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((department == null) ? 0 : department.hashCode()); result = prime * result + ((id == null) ? 0 : id.hashCode()); 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 (getClass() != obj.getClass()) return false; Employee other = (Employee) obj; if (age != other.age) return false; if (department == null) { if (other.department != null) return false; } else if (!department.equals(other.department)) return false; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } //下面是变量的get、set函数 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } //toString函数 @Override public String toString() { return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", department=" + department + "]"; } //这里是我们自己写的compareTo(Object o)函数 @Override public int compareTo(Object o) { if(o instanceof Employee){ Employee e=(Employee)o; return this.age-e.age; //直接返回年龄的差,返回大于,等于,小于零。 } return 0; } }
MySort1:
import java.util.HashSet; import java.util.Iterator; import java.util.TreeSet; public class MySort1 { public static void main(String[] args) { HashSet set=new HashSet();//该方法:HashSet不能自定义排序,由Employee类中的hashCode()方法的返回值来决定元素的先后顺序。hashCode()方法的返回值是由当前对象本身的数据决定,不能和其他元素进行对比 //TreeSet set=new TreeSet();//该方法:TreeSet能自定义排序,有Employee类中的compareTo()方法的返回值来决定元素的先后顺序。compareTo()方法是由当前对象和参数对象的数据对比结构决定,且对比方式是由我们自己写 //set.add(new String("adcf")); //在这里添加“字符串”元素是可行的,因为Employee类中的compareTo(Object o)方法中可以接收任意类型的参数对象。 set.add(new Employee("Jack", 25)); //set.add(new String("adcf"));在这里添加“字符串”元素是不可行的,因为String类中的compareTo(Object o)方法,不能把原先已经加入集合的Employee对象当作参数传入String类的compareTo(String str)进行比较大小。而如果把该句放在其他add语句之前就可行,因为那样就是把先加入集合的“字符串”作为参数去调用Employee中的compareTo(Object o)方法。 set.add(new Employee("Mike", 26)); set.add(new Employee("Mary", 23)); Iterator it=set.iterator(); //使用迭代器读取数据 //输出 while(it.hasNext()){ System.out.println(it.next()); } } }
运行结果:
一、集合排序(方法一)
概念:java.util.Comparator接口适用于一个类有自然顺序的时候。假定对象集合是同一类型,该接口允许把集合排序成自然顺序。该接口中的compare ( T o1, To2)方法: 比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负、零或正整数。
实现要点:让容器在构造时加入比较器对象。
代码示例:(以TreeMap集合为例,让其中的员工按编号倒序排列。中文排序问题:比较函数对于英文字母与数字等ASCII码中的字符排序都没问题,但中文排序则明显不正确。这主要是Java中使用中文编码GB2312或GBK时,char型转换成int型的过程出现了比较大的偏差。这偏差是由compare方法导致的,因此我们可以自己实现Comparator接口。另外,国际化问题可用Collator类来解决。
java.text.Collator类,提供以与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。)
MySort2:
import java.text.CollationKey; import java.text.Collator; import java.util.Comparator; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class MySort2 { public static void main(String[] args) { sort1(); //用自定义比较器(compareTo(Object o))来排序 sort2(); //中文排序 } //用自定义比较器(compareTo(Object o))来排序 private static void sort1() { TreeMap map=new TreeMap(new MyCmp());//给TreeMap集合外加一个我们自己写的比较器MyCmp(compareTo(Object o1,Object o2)),由比较器MyCmp(compareTo(Object o1,Object o2))来决定元素的排序方式。 //加元素到map中 map.put("1002", "周军"); map.put("1003", "刘军"); map.put("1012", "王军"); map.put("1001", "李军"); Set entries=map.entrySet();//返回此映射中包含的映射关系的 Set 视图 Iterator it=entries.iterator(); //返回在此 set 中的元素上进行迭代的迭代器 //输出 System.out.println("Sort1测试:-------------------------------"); while(it.hasNext()){ //如果仍有元素可以迭代,则返回 true Map.Entry en=(Map.Entry)it.next(); //返回迭代的下一个元素 System.out.println(en.getKey()+","+en.getValue()); } } private static void sort2() { TreeMap map=new TreeMap(new MyCmp2());//给TreeMap集合外加一个我们自己写的比较器MyCmp2(compareTo(Object o1,Object o2)),由比较器MyCmp2(compareTo(Object o1,Object o2))来决定元素的排序方式。 //加元素到map中 map.put("周军","1002"); map.put("刘军","1003"); map.put("王军",new Employee("Mike",26)); map.put("李军",new Employee("Rose",23)); Set entries=map.entrySet();//返回此映射中包含的映射关系的 Set 视图 Iterator it=entries.iterator(); //返回在此 set 中的元素上进行迭代的迭代器 //输出 System.out.println("Sort2测试:-------------------------------"); while(it.hasNext()){ //如果仍有元素可以迭代,则返回 true Map.Entry en=(Map.Entry)it.next(); //返回迭代的下一个元素 System.out.println(en.getKey()+","+en.getValue()); } } } //比较器,(按从小到大的顺序排列) class MyCmp implements Comparator{ @Override public int compare(Object o1, Object o2) { return Integer.parseInt(o1.toString())-Integer.parseInt(o2.toString()); } } class MyCmp2 implements Comparator{ Collator c=Collator.getInstance(); //获取当前默认语言环境的 Collator @Override public int compare(Object o1, Object o2) { // 将该 String 转换为一系列可以和其他 CollationKey 按位进行比较的位 CollationKey key1=c.getCollationKey(o1.toString()); CollationKey key2=c.getCollationKey(o2.toString()); return key2.compareTo(key1); //比较此 Key1 与Key2 } }
结果:
三、综述
在JDK1.2中,有14个类实现了Comparable接口,这些类中指定的自然排序如下:
1、BigDecimal,BigInteger,Byte,Double,Float,Integer,Long,Short按数字大小排序
2、Character 按Unicode值的数字大小排序
3、CollationKey 按语言环境敏感的字符串排序
4、Date 按年代排序
5、File 按系统特定的路径名的全限定字符的Unicode值排序
6、ObjectStreamField 按名字中字符的Unicode值排序
7、String 按字符串中字符Unicode值排序
如果一个类不能或不便于实现java.lang.Comparable接口,则可以用实现比较器Comparator接口的方法提供自己的排序行为。同样,如果缺省Comparable行为满足不了工程需要,也可以提供自己的Comparator。
四、编程练习
定义一个类,类里面有一个属性col,类型是集合类型Collection,实现下列方法:可以向col里面添加数据、修改数据、查询数据、删除数据。也就是把这个col当作一个数据存储的容器,对其实现数据的增删改查的方法。
代码实现:
import java.util.ArrayList; import java.util.Collection; public class MyCollection { private Collection col=new ArrayList(); //软件工程,设计方法:自顶而下 //增加 public boolean add(Object obj){ return col.add(obj); //将指定的元素添加到此列表的尾部 } //删除 public boolean delete(Object obj){ return col.remove(obj); //移除此列表中首次出现的指定元素(如果存在) } //修改 public boolean update(Object oldObj,Object newObj){ Object objs[]=col.toArray(); //按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组 col.clear(); //移除此列表中的所有元素 for(int i=0;i<objs.length;i++){ if(objs[i].equals(oldObj)){ objs[i]=newObj; //把需要替换的元素找出来,用newObj替换 } col.add(objs[i]); } return true; } //查找 public Collection getAll(){ return col; } }
版权声明:本文为博主原创文章,未经博主允许不得转载。