Java类集 _排序及重复元素说明

1、掌握TreeSet 的排序原理

2、掌握Set 接口中重复元素的定义

TreeSet 类的内容是可以排序的,那么现在我任意给出一个类,观察能否排序的操作。

import java.util.Set ;
import java.util.TreeSet ;
class Person{
	private String name ;
	private int age ;
	public Person(String name,int age){
		this.name = name ;
		this.age = age ;
	}
	public String gtoString(){
		return "姓名:" + this.name + ";年龄:" + this.age ;
	}
};
public class TreeSetDemo02{
	public static void main(String args[]){
		Set<Person> allSet = new TreeSet<Person>() ;
		allSet.add(new Person("张三",30)) ;
		allSet.add(new Person("李四",31)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("赵六",33)) ;
		allSet.add(new Person("孙七",33)) ;
		System.out.println(allSet) ;
	}
};
执行时出现了以下错误:

Exception in thread "main" java.lang.ClassCastException: Person cannot be cast t
o java.lang.Comparable
        at java.util.TreeMap.compare(TreeMap.java:1188)
        at java.util.TreeMap.put(TreeMap.java:531)
        at java.util.TreeSet.add(TreeSet.java:255)
        at TreeSetDemo02.main(TreeSetDemo02.java:17)

Comparable 之前曾经讲解过主要是进行排序的操作接口,一个对象数组要想排序,则依靠Comparable 接口完成。那么对于TreeSet 也一样,如果要想使用TreeSet 进行排序的操作,则对象所在的类也必须实现Comparable 接口。

import java.util.Set ;
import java.util.TreeSet ;
class Person implements Comparable<Person>{
	private String name ;
	private int age ;
	public Person(String name,int age){
		this.name = name ;
		this.age = age ;
	}
	public String toString(){
		return "姓名:" + this.name + ";年龄:" + this.age ;
	}
	public int compareTo(Person per){
		if(this.age>per.age){
			return 1 ;
		}else if(this.age<per.age){
			return -1 ;
		}else{
			return 0 ;
		}
	}
};
public class TreeSetDemo03{
	public static void main(String args[]){
		Set<Person> allSet = new TreeSet<Person>() ;
		allSet.add(new Person("张三",30)) ;
		allSet.add(new Person("李四",31)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("赵六",33)) ;
		allSet.add(new Person("孙七",33)) ;
		System.out.println(allSet) ;
	}
};
String 类既然可以使用TreeSet 排序,则String 中肯定已经实现了Comparable 接口
此时,是可以排序了,但是结果有问题。

[姓名:张三;年龄:30,姓名:李四;年龄:31,姓名:王五;年龄:32,姓名:赵六;年龄:33]

发现在此时去掉了重复的元素,但是依靠的是Comparable 接口完成的。孙七没有加入进来,因为两个的年龄是完全一样的,而此时的 Comparable 接口比较的只是年龄,所以为了保证正确,所有的属性都应该进行比较:

import java.util.Set ;
import java.util.TreeSet ;
class Person implements Comparable<Person>{
	private String name ;
	private int age ;
	public Person(String name,int age){
		this.name = name ;
		this.age = age ;
	}
	public String toString(){
		return "姓名:" + this.name + ";年龄:" + this.age ;
	}
	public int compareTo(Person per){
		if(this.age>per.age){
			return 1 ;
		}else if(this.age<per.age){
			return -1 ;
		}else{
			return this.name.compareTo(per.name) ;	// 调用String中的compareTo()方法
		}
	}
};
public class TreeSetDemo04{
	public static void main(String args[]){
		Set<Person> allSet = new TreeSet<Person>() ;
		allSet.add(new Person("张三",30)) ;
		allSet.add(new Person("李四",31)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("赵六",33)) ;
		allSet.add(new Person("孙七",33)) ;
		System.out.println(allSet) ;
	}
};
此时去掉的重复元素并不是真正意义上的重复元素的取消。

import java.util.Set ;
import java.util.HashSet ;
class Person{
	private String name ;
	private int age ;
	public Person(String name,int age){
		this.name = name ;
		this.age = age ;
	}
	public String toString(){
		return "姓名:" + this.name + ";年龄:" + this.age ;
	}
};
public class RepeatDemo01{
	public static void main(String args[]){
		Set<Person> allSet = new HashSet<Person>() ;
		allSet.add(new Person("张三",30)) ;
		allSet.add(new Person("李四",31)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("赵六",33)) ;
		allSet.add(new Person("孙七",33)) ;
		System.out.println(allSet) ;
	}
};
此时,并没有去掉重复的元素,那么重复元素该如何取消呢:
如果要想取消掉重复元素,则需要Object 类中的两个方法帮助

hashCode():表示一个唯一的编码,一般通过计算表示

equals():进行对象的比较操作。

import java.util.Set ;
import java.util.HashSet ;
class Person{
	private String name ;
	private int age ;
	public Person(String name,int age){
		this.name = name ;
		this.age = age ;
	}
	public boolean equals(Object obj){	// 覆写equals,完成对象比较
		if(this==obj){
			return true ;
		}
		if(!(obj instanceof Person)){
			return false ;
		}
		Person p = (Person)obj ;	// 向下转型
		if(this.name.equals(p.name)&&this.age==p.age){
			return true ;
		}else{
			return false ;
		}
	}
	public int hashCode(){
		return this.name.hashCode() * this.age	; // 定义一个公式
	}
	public String toString(){
		return "姓名:" + this.name + ";年龄:" + this.age ;
	}
};
public class RepeatDemo02{
	public static void main(String args[]){
		Set<Person> allSet = new HashSet<Person>() ;
		allSet.add(new Person("张三",30)) ;
		allSet.add(new Person("李四",31)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("王五",32)) ;
		allSet.add(new Person("赵六",33)) ;
		allSet.add(new Person("孙七",33)) ;
		System.out.println(allSet) ;
	}
};
如果要想使用 Set,则就必须注意以上的两个问题。

总结:

1、之前曾经强调过:一个好的类应该覆写Object 类中的equals()、hashCode()、toString() 三个方法,实际上在String 中已经全部覆写完成了

2、Set 接口依靠hashCode() 和equals() 完成重复元素的判断,关于这一点在日后的Map 接口中也有体现

3、TreeSet 依靠 Comparable 接口完成排序的操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值