第十一章 集合(Set)
- 集合的特点
- 不存放重复的元素
- 常用于去重
- 存放新增 IP,统计新增 IP 量
- 存放词汇,统计词汇量
- . . .
集合的接口定义
集合的接口文件(interface),所有实现的集合都需要实现该接口
public interface Set<E> {
int size(); //元素数量
boolean isEmpty(); // 是否为空
void claer(); // 清空集合
boolean contains(E element); // 是否包含element元素
void add(E element); // 添加element元素
void remove(E element); // 删除element元素
void traversal(Visitor<E> visitor); // 通过访问器遍历
public static abstract class Visitor<E>{ // 访问器
boolean stop;
public abstract boolean visit(E element);
}
}
- 思考:集合的内部实现能否直接利用以前学过的数据结构?
- 动态数组
- 链表
- 二叉搜索树(AVL树、红黑树)
双向链表 LinkedList 实现 ListSet
package cn.xx.java.set;
import cn.xx.java.list.LinkedList;
import cn.xx.java.list.List;
/**
* 双向链表 LinkedList 实现 ListSet
*
* @author xiexu
* @create 2021-08-12 11:16 上午
*/
public class ListSet<E> implements Set<E> {
private List<E> list = new LinkedList<>();
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void clear() {
list.clear();
}
@Override
public boolean contains(E elements) {
return list.contains(elements);
}
@Override
public void add(E elements) {
int index = list.indexOf(elements);
if (index != List.ELEMENT_NOT_FOUND) { //存在就覆盖
list.set(index, elements);
} else { //不存在就添加
list.add(elements);
}
}
@Override
public void remove(E elements) {
int index = list.indexOf(elements);
if (index != List.ELEMENT_NOT_FOUND) {
list.remove(index);
}
}
@Override
public void traversal(Visitor<E> visitor) {
if (visitor == null) {
return;
}
int size = list.size();
for (int i = 0; i < size; i++) {
if (visitor.visit(list.get(i))) {
return;
}
}
}
}
红黑树 RBTree 实现 TreeSet
package cn.xx.java.set;
import cn.xx.java.tree.BinaryTree;
import cn.xx.java.tree.RBTree;
/**
* 红黑树 RBTree 实现 TreeSet
*
* @author xiexu
* @create 2021-08-12 11:51 上午
*/
public class TreeSet<E> implements Set<E> {
private RBTree<E> tree = new RBTree<>();
@Override
public int size() {
return tree.size();
}
@Override
public boolean isEmpty() {
return tree.isEmpty();
}
@Override
public void clear() {
tree.clear();
}
@Override
public boolean contains(E elements) {
return tree.contains(elements);
}
@Override
public void add(E elements) {
tree.add(elements); //默认就是去重的
}
@Override
public void remove(E elements) {
tree.remove(elements);
}
@Override
public void traversal(Visitor<E> visitor) {
tree.inorder(new BinaryTree.Visitor<E>() {
@Override
public boolean visit(E element) {
return visitor.visit(element);
}
});
}
}
TreeMap 实现 TreeSet
package cn.xx.java.set;
import cn.xx.java.map.Map;
import cn.xx.java.map.TreeMap;
/**
* @author xiexu
* @create 2021-08-13 2:00 下午
*/
public class TreeSet<E> implements Set<E> {
Map<E, Object> map = new TreeMap<>();
@Override
public int size() {
return map.size();
}
@Override
public boolean isEmpty() {
return map.isEmpty();
}
@Override
public void clear() {
map.clear();
}
@Override
public boolean contains(E elements) {
return map.containsKey(elements);
}
@Override
public void add(E elements) {
map.put(elements, null);
}
@Override
public void remove(E elements) {
map.remove(elements);
}
@Override
public void traversal(Visitor<E> visitor) {
map.traversal(new Map.Visitor<E, Object>() {
@Override
public boolean visit(E key, Object value) {
return visitor.visit(key);
}
});
}
}
HashMap 实现 HashSet
package cn.xx.java.set;
import cn.xx.java.map.HashMap;
import cn.xx.java.map.Map;
/**
* @author xiexu
* @create 2021-08-20 9:48 上午
*/
public class HashSet<E> implements Set<E> {
private HashMap<E, Object> map = new HashMap<>();
@Override
public int size() {
return map.size();
}
@Override
public boolean isEmpty() {
return map.isEmpty();
}
@Override
public void clear() {
map.clear();
}
@Override
public boolean contains(E elements) {
return map.containsKey(elements);
}
@Override
public void add(E elements) {
map.put(elements, null);
}
@Override
public void remove(E elements) {
map.remove(elements);
}
@Override
public void traversal(Visitor<E> visitor) {
map.traversal(new Map.Visitor<E, Object>() {
@Override
public boolean visit(E key, Object value) {
return visitor.visit(key);
}
});
}
}
LinkedHashMap 实现 LinkedHashSet
package cn.xx.java.set;
import cn.xx.java.map.LinkedHashMap;
import cn.xx.java.map.Map;
/**
* @author xiexu
* @create 2021-08-20 9:48 上午
*/
public class LinkedHashSet<E> implements Set<E> {
private LinkedHashMap<E, Object> map = new LinkedHashMap<>();
@Override
public int size() {
return map.size();
}
@Override
public boolean isEmpty() {
return map.isEmpty();
}
@Override
public void clear() {
map.clear();
}
@Override
public boolean contains(E elements) {
return map.containsKey(elements);
}
@Override
public void add(E elements) {
map.put(elements, null);
}
@Override
public void remove(E elements) {
map.remove(elements);
}
@Override
public void traversal(Visitor<E> visitor) {
map.traversal(new Map.Visitor<E, Object>() {
@Override
public boolean visit(E key, Object value) {
return visitor.visit(key);
}
});
}
}
练习
349. 两个数组的交集 - 力扣(LeetCode)
package 数组;
import java.util.HashSet;
/**
* https://leetcode-cn.com/problems/intersection-of-two-arrays/
*
* @author xiexu
* @create 2021-08-13 8:23 上午
*/
public class _349_两个数组的交集 {
public int[] intersection(int[] nums1, int[] nums2) {
HashSet<Integer> set1 = new HashSet<>();
HashSet<Integer> set2 = new HashSet<>();
for (int i = 0; i < nums1.length; i++) {
set1.add(nums1[i]);
}
for (int i = 0; i < nums2.length; i++) {
if (set1.contains(nums2[i])) {
set2.add(nums2[i]);
}
}
int index = 0;
int[] arr = new int[set2.size()];
for (int i : set2) {
arr[index++] = i;
}
return arr;
}
}