Set是一个不包含重复元素的Collection,Set允许包含null元素,但只允许一个Set集合包含一个null元素,也就是说Set集合不能包含重复的元素
1.认识Set接口
Set集合的对象不按特定方式排序,只是简单的把对象加入到集合中。
public interface Set<E> extends Collection<E>
- 1
可以看出Set接口与List接口没有多大区别,而Set接口也没有对Collection接口进行扩充。但Set接口比Collection接口有更严格的约束条件——不允许元素重复,Set接口也不像List接口的实例可以双向输出,也没有get(int index)方法。
Set接口中常用的实现类有HashSet和TreeSet。HashSet类可以快速第定位一个元素,但是放到HashSet集合中的元素需要重写equals()和hashCode()方法,TreeSet集合将放入其中的元素按序存放
2.散列集:HashSet
HashSet类是按照哈希算法来存取集合中的元素的,使用哈希算法可以提高存取的效率,当向HashSet集合中添加元素时,就会调用该元素的hashCode()方法,获取其哈希吗值,然后根据这个哈希吗值计算出该元素的存放位置。HashSet集合具有以下特点:
- 不能保证元素的排列顺序,集合中元素的顺序随时可能发生改变
- 集合中最多允许存在一个null元素
- HashSet集合不是线程同步的
没有重写equals()和hashCode()方法时的HashSet集合:
import java.util.Set;
import java.util.HashSet;
class Person {
private String name; //定义name属性
private int age; //定义age属性
public Person(){ //无参构造方法
}
public Person(String name,int age){ //有参构造方法,初始化成员属性
this.name=name;
this.age=age;
}
public String toString(){ //重写toString()方法
return ("姓名:"+name+",年龄:"+age+"\n");
}
}
public class HashSetDemo01 {
public static void main(String[] args) {
Set<Person> set = new HashSet<Person>(); //通过HashSet实例化Set
set.add(new Person("小强",21)); //添加元素
set.add(new Person("小伟",23)); //添加元素
set.add(new Person("小强",21)); //添加重复元素
set.add(new Person("小强",21)); //添加重复元素
set.add(new Person("小琴",20)); //添加元素
set.add(new Person("小婷",20)); //添加元素
System.out.println(set); //输出集合中所有的元素
}
}
[姓名:小强,年龄:21
, 姓名:小伟,年龄:23
, 姓名:小强,年龄:21
, 姓名:小琴,年龄:20
, 姓名:小婷,年龄:20
, 姓名:小强,年龄:21
]
此时集合中存在3个new Person(“小强” 21),之所以出现这种看似与前面Set集合不允许出现重复元素相违背的现象,是因为这3个new Person(“小强” 21)是不在同一个内存地址的对象,默认调用Object类中的equals()方法比较的结果是false,所以HashSet集合认为他是不同的元素,为了避免这种现象,需要重写equals()方法:
import java.util.Set;
import java.util.HashSet;
class Person {
private String name; //定义name属性
private int age; //定义age属性
public Person(){ //无参构造方法
}
public Person(String name,int age){ //有参构造方法,初始化成员属性
this.name=name;
this.age=age;
}
public boolean equals(Object o){ //重写equals()方法
if (this==o) { //判断当前对象与指定对象是否相等
return true;
}
if (o==null) { //判断指定对象是否为空
return false;
}
if (!(o instanceof Person)) { //判断指定对象是否为Person的实例
return false;
}
Person per=(Person)o; //将指定对象转为Person实例
if (this.name.equals(per.name)&&this.age==per.age) { //比较对象的属性是否相等
return true;
}else{
return false;
}
}
public int hashCode(){ //重写hashCode()方法
final int prime=13;
int result=13;
result=prime*result+((name==null)?0:name.hashCode());
result=prime*result+age;
return result;
}
public String toString(){ //重写toString()方法
return ("姓名:"+name+",年龄:"+age+"\n");
}
}
public class HashSetDemo02 {
public static void main(String[] args) {
Set<Person> set = new HashSet<Person>(); //通过HashSet实例化Set
set.add(new Person("小强",21)); //添加元素
set.add(new Person("小伟",23)); //添加元素
set.add(new Person("小强",21)); //添加重复元素
set.add(new Person("小强",21)); //添加重复元素
set.add(new Person("小琴",20)); //添加元素
set.add(new Person("小婷",20)); //添加元素
System.out.println(set); //输出集合中所有的元素
}
}
[:小伟,年龄:23
, 姓名:小琴,年龄:20
, 姓名:小婷,年龄:20
, 姓名:小强,年龄:21
]
3.数集:TreeSet类
public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>,Cloneable,Serializable
- 1
TreeSet类实现了java.util包中的Set接口和SoredSet接口,TreeSet集合元素在默认情况下是升序排序。
TreeSet集合的方法:
- TreeSet() 构造一个新的TreeSet实例,该集合的元素以升序排序
- TreeSet(Comparator<? extends E> c) 构造一个新的TreeSet实例,该集合的元素以升序排序
- add(E e) 若元素e不在集合中,就将其添加进去
- addAll(Collection<? extends E> c) 将指定的集合c中的所有元素添加到集合