set接口
set接口:无序的,不可重复的
- HashSet:作为set接口的主要实现类;线程不安全,可以存储NUll值
- LinkedHashSet:是HashSet的子类,遍历其内部数据时,按照添加顺序遍历
- TreeSet:可以按照添加对象指定属性进行排序
Set接口中没有额外定义新的方法
HashSet
关于无序性与不可重复性
无序性:
不等于随机性。以HashSet为例,存储数据在底层数组中并非按照数组索引顺序添加,而是按照数据的哈希值决定
不可重复性:
保证添加的元素按照equals()判断时,不能返回true。即:相同的元素只能添加一个。结合添加元素的过程理解
添加元素的过程
向HashSet中添加元素a,首先调用hashCode()方法,计算a的哈希值此哈希值通过某种算法计算出在HashSet底层数组中的存放位置(索引值)判断这个位置是否已经有元素;
- 如果没有,则添加成功
- 如果有其他元素b(或以链表形式存在的多个元素),则比较a与b的哈希值
- 如果哈希值不相同,则元素a添加成功
- 如果哈希值相同,则调用a所在类的equals方法
- 返回true,则a与b相同,添加失败
- 返回false,添加成功
public class SetTest {
public static void main(String[] args) {
Set set = new HashSet();
set.add(456);
set.add(123);
set.add("AA");
set.add("CC");
set.add(new Person("Tom", 12));
set.add(129);
// System.out.println(set);
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
LinkedHashSet
- LinkedHashSet作为HashSet的子类, 在添加数据的同时,还维护了两个引用,记录此数据前后两个数据对于频繁地遍历操作,效率更高
- 继承Collection接口中的方法
public class LinkedHashSetTest {
public static void main(String[] args) {
//LinkedHashSet作为HashSet的子类,
// 在添加数据的同时,还维护了两个引用,记录此数据前后两个数据
//对于频繁地遍历操作,效率更高
Set set = new LinkedHashSet();
set.add(456);
set.add(123);
set.add("AA");
set.add("CC");
set.add(new Person("Tom", 12));
set.add(129);
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
TreeSet
- 向TreeSet中添加的数据,要求是相同类的对象
- 两种排序方式:自然排序(实现Comparable接口) 和定制排序(comparator)
- 自然排序中,比较两个对象是否相等的标准为:compareTo()返回0,不再是equals()。
- 定制排序中,比较两个对象是否相同的标准为:compare()返回0,而不是equals()。 TreeSet中是通过红黑二叉树来实现对添加的数据进行去重排序,其中排序需要两种比较方式的重写来规定进行排序的类的属性。
public static void main(String[] args) {
TreeSet set = new TreeSet();
//此处向TreeSet中添加的必须是同一类的对象
// set.add(456);
// set.add(123);
// set.add("AA");
// set.add("CC");
// set.add(new Person("Tom", 12));
/*
set.add(34);
set.add(-34);
set.add(43);
set.add(11);
set.add(8);
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}*/
set.add(new Person("Tom", 12));
set.add(new Person("Jerry", 32));
set.add(new Person("Jim", 2));
set.add(new Person("Mike", 65));
set.add(new Person("Jack", 33));
set.add(new Person("Jack", 56));
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("**********************");
//通过定制排序实现年龄从小到大的顺序
Comparator com=new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Person && o2 instanceof Person) {
Person p1 = (Person) o1;
Person p2 = (Person) o2;
return Integer.compare(p1.getAge(), p2.getAge());
} else {
throw new RuntimeException("输入类型不一致");
}
}
};
TreeSet set2 = new TreeSet(com);
set2.add(new Person("Tom", 12));
set2.add(new Person("Jerry", 32));
set2.add(new Person("Jim", 2));
set2.add(new Person("Mike", 65));
set2.add(new Person("Jack", 33));
set2.add(new Person("Jack", 56));
iterator = set2.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}