前言
上一节介绍了Collecton接口,List接口,以及其子类ArrayList与vector的相关概念及其基本应用,本节将继续学习Collection接口的另一个子接口及其子类的基本概念以及应用
Set接口
Set接口的定义
Set接口也是Collection接口的子接口,但是与Collection或List接口不同的是,Set接口中不能加入重复的元素。Set接口的定义如下:
public interface Set<E> extends Collection<E>
从定义上可以发现,Set接口与List接口的定义并没有太大的区别。但是Set接口的主要方法与Collection是一致的,也就是说Set接口并没有对Collection接口进行扩充,只是比Collection接口的要求更加严格了,不能增加重复元素。
Set接口的实例无法像List接口那样可以进行双向输出,因为此接口没有提供像List接口定义的get(int index)方法。
Set接口的常用子类
1. 散列的存放: HashSet
HashSet是Set接口的一个子类,主要的特点是,里面不能存放重复元素,而且采用散列的存储方式,所以没有顺序。
范例
package ljz;
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo01 {
public static void main(String[] args){
Set<String> allSet=new HashSet<String>();
allSet.add("A");
allSet.add("B");
allSet.add("C");
allSet.add("D");
allSet.add("E");
System.out.print(allSet);
}
}
程序运行结果:
[D,A,C,B,E]
从程序的运行结果可以看出,对于重复元素只会增加一次,而且程序运行时向集合中加入元素的顺序并不是集合中的保存顺序,证明HashSet类中的元素是无序排列的。
2.有序的存放:TreeSet
如果想对输入的数据进行有序的排列,则要使用TreeSet子类。TreeSet类的定义如下:
public class TreeSet<E> extends AbstractSet<E>
implements SortedSet<E>,Cloneable,SeriaLizable
而AbstractSet也是继承AbstractCollection,此类的定义如下:
public abstract class AbstractSet<E> extends
AbstractCollection<E> implements Set<E>
范例
- 验证TreeSet类
package ljz;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetDemo01 {
public static void main(String[] args){
Set<String> allSet=new TreeSet<String>();
allSet.add("C");
allSet.add("C");
allSet.add("C");
allSet.add("D");
allSet.add("B");
allSet.add("A");
allSet.add("E");
System.out.println(allSet);
}
}
程序运行结果:
[A, B, C, D, E]
程序在向集合中插入数据时是没有顺序的,但是输出之后数据是有序的,所以TreeSet是可以排序的子类。
指定排序规则
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) ;
}
};
程序运行结果:
[姓名:张三;年龄:30;姓名:李四;年龄:31;姓名:王五;年龄:32;姓名:赵六;年龄:33]
提问:如何判断对象是否重复?
想判断对象是否重复,则必须覆写Object类中的equals()方法,才能完成对象是否相等的判断,但是只覆写equals()方法是不够的,还需要覆写hashCode()方法,此方法表示一个哈希编码,可以简单地理解为表示一个对象的编码。一般的哈希码是通过公式计算的,可以将类中的全部属性进行适当的计算,以求出一个不会重复的哈希码
关于hashCode的理解
关于hashCode也可以从实际生活中理解,例如:每个人都会有一个唯一的身份证号,当进行入口省察的时候,首先肯定会检查身份证是否一致(相当于使用hashCode),如果一致的话,则在将每个人的信息进行匹配(相当于对象比较使用equals()),如果全部符合,则表示通过审查。
范例:
import java.util.HashSet;
import java.util.Set;
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){
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 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) ;
}
};
程序运行结果:
[姓名:王五;年龄:32,姓名:李四;年龄:31,姓名:张三;年龄:30,姓名:孙七;年龄:33,姓名:赵六;年龄:33]
从最后输出的结果中可以发现,集合中的重复内容消失了,就是因为equals和hashCode共同作用的结果
SortedSet接口
从TreeSet类的定义中可以发现,TreeSet中实现了SortedSet接口,此接口主要用于排序操作,即实现此接口的子类都属于排序的子类。SortedSet接口的定义如下:
public interface SortedSet<E> extends Set<E>
发现此接口也继承了Set接口。
范例
import java.util.Set;
import java.util.SortedSet;
public class TreeSetDemo05{
public static void main(String[] args){
SortedSet<String> allSet=new TreeSet<String>(){
allSet.add("A");
allSet.add("B");
allSet.add("C");
allSet.add("D");
allSet.add("E");
System.out.println("第一个元素:"+allSet.first());
System.out.println("最后一个元素:"+allSet.last());
System.out.println("headSet元素:"+allSet.headSet("C"));
System.out.println("tailSet元素:"+allSet.tailSet("C"));
System.out.println("subSet元素:"+allSet.subSet("B","D"));
}
}
程序运行结果:
第一个元素:A
最后一个元素:E
headSet元素:[A, B]
tailSet元素:[C, D, E]
subSet元素:[B, C]
未完待续!