集合的典型应用:
客户统计
词汇量统计
1、基于二分搜索树的集合
定义接口ISet
public interface ISet<E> {
void add(E e);
void remove(E e);
boolean contains(E e);
int getSize();
boolean isEmpty();
}
定义基于二分搜索树的集合
public class BinarySearchTreeSet<E extends Comparable<E>> implements ISet<E> {
private BinarySearchTree<E> bst;
public BinarySearchTreeSet(){
bst = new BinarySearchTree<E>();
}
public void add(E e) {
bst.add(e);
}
public void remove(E e) {
bst.remove(e);
}
public boolean contains(E e) {
return bst.contains(e);
}
public int getSize() {
return bst.size();
}
public boolean isEmpty() {
return bst.isEmpty();
}
}
2、 基于链表的集合
public class LinkedListSet<E> implements ISet<E> {
private LinkedList<E> linkedList;
public LinkedListSet(){
linkedList= new LinkedList<E>();
}
public void add(E e) {
if(!linkedList.contains(e)){
linkedList.addFirst(e);
}
}
public void remove(E e) {
linkedList.removeElement(e);
}
public boolean contains(E e) {
return linkedList.contains(e);
}
public int getSize() {
return linkedList.getSize();
}
public boolean isEmpty() {
return linkedList.isEmpty();
}
}
3、基于二分搜索树结合和链表结合性能对比
public class TwoSetTest {
private static double testSet(ISet<String> set){
long startTime = System.nanoTime();
String[] arr = {"张三", "李四","王五", "赵六","张三丰","李思明","王老五","赵明"};
for(int i = 0; i < 5000; i++){
for(String str : arr){
set.add(str +i);
}
}
long endTme = System.nanoTime();
return (endTme - startTime) / 1000000000.0;
}
public static void main(String[] args) {
BinarySearchTreeSet<String> set2 = new BinarySearchTreeSet<String>();
double time2 = testSet(set2);
System.out.println("二分搜索树Set花费" + time2);
LinkedListSet<String> set1 = new LinkedListSet<String>();
double time1 = testSet(set1);
System.out.println("链表Set花费" + time1);
}
}
输出结果如下:
二分搜索树Set花费0.040670373 链表Set花费7.014404433
可以发现,二分搜索树的Set花费的时间明显小于基于链表的Set
两种集合的时间复杂度比较
| LinkedListSet |
BinarySearchTreeSet |
|
| 增add | O(n) | O(h), 或者平均O(logn) 最差O(n) |
| 查contains | O(n) | O(h) ,或者平均O(logn) 最差O(n) |
| 删remove | O(n) | O(h), 或者平均O(logn) 最差O(n) |
h为数的高度。n和h的关系 h = logn , 2^h = n
BinarySearchTreeSet 最差O(n),比如

最差是O(n),我们可以使用平衡二叉树,这个后面再进行介绍。
4、leetcode集合的使用题目 804 唯一摩尔斯密码词
https://leetcode-cn.com/problems/unique-morse-code-words/
题目描述
国际摩尔斯密码定义一种标准编码方式,将每个字母对应于一个由一系列点和短线组成的字符串, 比如: "a" 对应 ".-", "b" 对应 "-...", "c" 对应 "-.-.", 等等。 为了方便,所有26个英文字母对应摩尔斯密码表如下: [".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."] 给定一个单词列表,每个单词可以写成每个字母对应摩尔斯密码的组合。例如,"cab" 可以写成 "-.-..--...",(即 "-.-." + ".-" + "-..." 字符串的结合)。我们将这样一个连接过程称作单词翻译。 返回我们可以获得所有词不同单词翻译的数量。 例如: 输入: words = ["gin", "zen", "gig", "msg"] 输出: 2 解释: 各单词翻译如下: "gin" -> "--...-." "zen" -> "--...-." "gig" -> "--...--." "msg" -> "--...--." 共有 2 种不同翻译, "--...-." 和 "--...--.".
解决方法:
public int uniqueMorseRepresentations(String[] words) {
TreeSet<String> treeSet = new TreeSet<String>();
String[] codes = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
for(String word : words){
StringBuilder res = new StringBuilder();
for(int i = 0; i < word.length(); i++){
res.append(codes[word.charAt(i) - 'a']);
}
treeSet.add(res.toString());
}
return treeSet.size();
}
5、有序集合和无序集合
有序集合中的元素具有顺序性,如基于搜索树的实现
无序集合中的元素没有顺序性,基于哈希表的实现
6、多重集合
集合中的元素可以重复。