一.特点
1.概述:
一般都是用于存储单列元素去重的时候才使用Set集合,Set集合继承于Collection
说到单列集合,包括Collection,List, Set ;而双列集合则有Map,存储键值对
我们都知道Map里面键值对是一 一映射关系,键不会重复,其实Set使用的底层也是HashMap,这样Set集合自然也不会存在重复数据,如果继续添加已有数据,则会返回false
1.使用Set最大的特点就是去重,去除重复元素
2.无序,输出顺序可能会无序
3.此类允许null元素
二.HashSet
1.底层原理
使用的是哈希表(散列表)存放数据,自然是无序的,
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
上面的源码显示的是add()方法,添加数据返回Boolean值,可以用此方法通过测试是否添加元素成功来了解集合中是否包含相同的元素。
除此之外,它得原理和map中的键不重复也是一样,初始容量也是默认为16,加载因子为0.75,扩充容量也和map中的HashMap一致,详情可以看我的博客:Java集合之Map(三)
2.子类LinkedHashSet
底层使用hash算法计算存储位置,同时使用链表来维护顺序,顺序与添加顺序一致。在查看检索时,效率比较高。
此实现与HashSet不同之处在于它维护了一个贯穿其所有条目的双向链表。 此链接列表定义迭代排序,即元素插入集合( 插入顺序 ) 的顺序 。 请注意,如果将元素重新插入到集合中,则不会影响插入顺序。 (如果s.add(e)在调用之前立即返回true则调用s.contains(e)将元素e重新插入到集s 。)
此实现使客户免于HashSet提供的未指定的,通常是混乱的排序,而不会产生与TreeSet相关的增加的成本。 无论原始集合的实现如何,它都可用于生成与原始集合具有相同顺序的集合的副本:
void foo(Set s) {
Set copy = new LinkedHashSet(s);
…
} 如果模块在输入上获取集合,复制它,然后返回其顺序由副本确定的结果,则此技术特别有用。 (客户通常会欣赏按照提交的顺序返回的内容。)
此类提供所有可选的Set操作,并允许null元素。 像HashSet ,它提供了基本操作(稳定的性能add , contains和remove ),假设散列函数散桶中适当的元件。 由于维护链表的额外费用,性能可能略低于HashSet性能,但有一个例外:迭代超过LinkedHashSet需要与集合大小成比例的时间,无论其容量如何。 对HashSet迭代可能更昂贵,需要与其容量成比例的时间。
package com.kaikeba.practice0925;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* Set集合
* 注意HashSet与其子类LinkedHashSet的区别
* HashSet移除后再重新插入该元素不改变顺序
* LinkedHashSet则其不然,改变顺序
*/
public class PracticeSet {
public static void main(String[] args) {
HashSet<String> set1 = new HashSet<String>();
set1.add("1");
set1.add("2");
set1.add("3");
set1.add("4");
set1.add("5");
set1.remove("2");
set1.add("2");
for(String i : set1){
System.out.println(i);
}
LinkedHashSet<String> set2 = new LinkedHashSet<>();
set2.add("6");
set2.add("7");
set2.add("8");
set2.remove("7");
set2.add("7");
for(String i : set2){
System.out.println(i);
}
}
}
输出打印:
注意两者之间remove后再addd的顺序区别
三.TreeSet
1. 底层原理
使用二叉树(红黑树)的数据结构维护元素的顺序
它使用的也是TreeMap,这里不详细介绍了,可以参见我的博客:Java集合之Map(三)
关于红黑树,可以参见这篇文章:红黑树的原理
2.排序
它是SortedSet子接口的实现类,除此它的底层是红黑树便意味着它可以进行排序功能
TreeSet<String> set3 = new TreeSet<String>();
set3.add("5");
set3.add("3");
set3.add("2");
set3.add("1");
set3.add("4");
for(String i : set3){
System.out.println(i);
}
很明显,输出为:
这里只是举了一个简单的例子,下面需要注意一下,也可以自己尝试一下
除此之外:我们可能一般使用面向对象,如Person对象,有name,id,age等属性
现在可以通过id给它排序吗?回答当然是可以的
只要去实现Comparable()接口,然后重写里面的CompareTo()方法便可以进行排序了