Java Set详解
引用:https://www.cnblogs.com/hongdada/p/6049895.html
Set:无顺序,不包含重复的元素
HashSet:为快速查找设计的Set。不会出现重复的元素,是无序的,此外它可以含有空元素。
LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。
import java.util.Iterator;
import java.util.LinkedHashSet;
public class Main {
public static void main(String[] args) {
LinkedHashSet books = new LinkedHashSet();
books.add("Java1");
books.add("Java2");
System.out.println(books);
//删除 Java
books.remove("Java1");
//重新添加 Java
books.add("Java1");
System.out.println(books);
for(Iterator iter = books.iterator(); iter.hasNext();){
Object value = iter.next();
System.out.println(value);
}
}
}
输出:
[Java1, Java2]
[Java2, Java1]
Java2
Java1
TreeSet: 保存次序的Set, 底层为树结构。使用它可以从Set中提取有序的序列,不能写入空数据
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
TreeSet nums = new TreeSet();
//向TreeSet中添加四个Integer对象
nums.add(5);
nums.add(2);
nums.add(10);
nums.add(-9);
//输出集合元素,看到集合元素已经处于排序状态
System.out.println(nums);
//输出集合里的第一个元素
System.out.println(nums.first());
//输出集合里的最后一个元素
System.out.println(nums.last());
//返回小于4的子集,不包含4
System.out.println(nums.headSet(4));
//返回大于5的子集,如果Set中包含5,子集中还包含5
System.out.println(nums.tailSet(5));
//返回大于等于-3,小于4的子集。
System.out.println(nums.subSet(-3 , 4));
}
}
输出:
[-9, 2, 5, 10]
-9
[-9, 2]
[5, 10]
[2]
与HashSet集合采用hash算法来决定元素的存储位置不同,TreeSet采用红黑树的数据结构来存储集合元素。
TreeSet支持两种排序方式: 自然排序、定制排序
TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间的大小关系,然后将集合元素按升序排序,即自然排序。
通过ComparaTor接口可以实现定制排序。
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new Comparator()
{
//根据M对象的age属性来决定大小
public int compare(Object o1, Object o2)
{
M m1 = (M)o1;
M m2 = (M)o2;
return m1.age > m2.age ? -1 : m1.age < m2.age ? 1 : 0;
}
});
ts.add(new M(5));
ts.add(new M(-3));
ts.add(new M(9));
System.out.println(ts);
for(Iterator iter = ts.iterator(); iter.hasNext();){
Object value = iter.next();
System.out.println(value);
}
}
}
class M
{
int age;
public M(int age)
{
this.age = age;
}
public String toString()
{
return "M[age:" + age + "]";
}
}
输出:
[M[age:9], M[age:5], M[age:-3]]
M[age:9]
M[age:5]
M[age:-3]
P.S.
- HashSet的性能总是比TreeSet好(特别是最常用的添加、查询元素等操作),因为TreeSet需要额外的红黑树算法来维护集合元素的次序。只有当需要一个保持排序的Set时,才应该使用TreeSet,否则都应该使用HashSet
- 对于普通的插入、删除操作,LinkedHashSet比HashSet要略慢一点,这是由维护链表所带来的开销造成的。不过,因为有了链表的存在,遍历LinkedHashSet会更快
- HashSet、TreeSet都是"线程不安全"的,通常可以通过Collections工具类的synchronizedSortedSet方法来"包装"该Set集合。
SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));