第十一章 集合(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)​

第十一章 集合(Set)_HashMap

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;
}

}