HashSet、LinkedHashSet和TreeSet的使用方法与应用场景
Set接口是Java集合框架中的重要组成部分,继承自Collection接口。Set表示一个不包含重复元素的集合,是数学上集合概念的抽象。
// Set接口基本使用示例
Set<String> fruits = new HashSet<>();
fruits.add("苹果");
fruits.add("香蕉");
fruits.add("苹果"); // 重复元素,不会被添加
System.out.println(fruits); // 输出: [香蕉, 苹果]
System.out.println(fruits.size()); // 输出: 2
Java提供了三种主要的Set实现类,每种都有其特定的特点和适用场景:
实现类 | 排序特性 | 性能 | 允许null | 线程安全 | 适用场景 |
---|---|---|---|---|---|
HashSet | 无序 | 最高 | 是 | 否 | 一般用途,高性能需求 |
LinkedHashSet | 插入顺序 | 中等 | 是 | 否 | 需要保持插入顺序 |
TreeSet | 自然排序 | 较低 | 否 | 否 | 需要排序和范围查询 |
// HashSet使用示例
HashSet<String> cities = new HashSet<>();
cities.add("北京");
cities.add("上海");
cities.add("广州");
cities.add("北京"); // 重复元素
System.out.println(cities); // 输出顺序不确定
System.out.println(cities.contains("北京")); // 快速查找: true
LinkedHashSet继承自HashSet,通过维护一个双向链表来保持元素的插入顺序。
// LinkedHashSet保持插入顺序
LinkedHashSet<String> orderedSet = new LinkedHashSet<>();
orderedSet.add("第一个");
orderedSet.add("第二个");
orderedSet.add("第三个");
System.out.println(orderedSet); // 输出: [第一个, 第二个, 第三个]
// 浏览历史示例
LinkedHashSet<String> history = new LinkedHashSet<>();
history.add("首页");
history.add("产品页");
history.add("首页"); // 重复访问,不改变顺序
System.out.println(history); // [首页, 产品页]
TreeSet基于红黑树(自平衡二叉搜索树)实现,提供了自动排序功能和丰富的导航方法。
// TreeSet自动排序
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(50);
numbers.add(20);
numbers.add(80);
numbers.add(10);
System.out.println(numbers); // 输出: [10, 20, 50, 80]
System.out.println(numbers.first()); // 最小值: 10
System.out.println(numbers.last()); // 最大值: 80
// 范围查询
System.out.println(numbers.subSet(20, 60)); // [20, 50]
System.out.println(numbers.headSet(50)); // [10, 20]
System.out.println(numbers.tailSet(50)); // [50, 80]
// 性能测试示例代码
public class SetPerformanceTest {
public static void testPerformance() {
int size = 100000;
// HashSet性能测试
long start = System.currentTimeMillis();
Set<Integer> hashSet = new HashSet<>();
for (int i = 0; i < size; i++) {
hashSet.add(i);
}
System.out.println("HashSet添加耗时: " +
(System.currentTimeMillis() - start) + "ms");
// LinkedHashSet性能测试
start = System.currentTimeMillis();
Set<Integer> linkedSet = new LinkedHashSet<>();
for (int i = 0; i < size; i++) {
linkedSet.add(i);
}
System.out.println("LinkedHashSet添加耗时: " +
(System.currentTimeMillis() - start) + "ms");
// TreeSet性能测试
start = System.currentTimeMillis();
Set<Integer> treeSet = new TreeSet<>();
for (int i = 0; i < size; i++) {
treeSet.add(i);
}
System.out.println("TreeSet添加耗时: " +
(System.currentTimeMillis() - start) + "ms");
}
}
// 用户权限管理系统
public class UserPermissionManager {
private Set<String> permissions = new HashSet<>();
public void addPermission(String permission) {
permissions.add(permission);
}
public boolean hasPermission(String permission) {
return permissions.contains(permission); // O(1)快速查找
}
public void displayPermissions() {
System.out.println("用户权限: " + permissions);
}
}
// 使用示例
UserPermissionManager manager = new UserPermissionManager();
manager.addPermission("READ");
manager.addPermission("WRITE");
manager.addPermission("DELETE");
manager.addPermission("READ"); // 重复权限
System.out.println(manager.hasPermission("WRITE")); // true
// 浏览历史管理
public class BrowsingHistory {
private LinkedHashSet<String> history = new LinkedHashSet<>();
private final int maxSize = 10;
public void visit(String page) {
// 如果已存在,先删除再添加(更新到最新位置)
if (history.contains(page)) {
history.remove(page);
}
history.add(page);
// 保持历史记录数量限制
if (history.size() > maxSize) {
String oldest = history.iterator().next();
history.remove(oldest);
}
}
public List<String> getRecentPages() {
return new ArrayList<>(history);
}
}
// 使用示例
BrowsingHistory history = new BrowsingHistory();
history.visit("首页");
history.visit("产品页");
history.visit("关于我们");
history.visit("首页"); // 重复访问,移到最新位置
System.out.println(history.getRecentPages()); // [产品页, 关于我们, 首页]
// 游戏排行榜
public class GameLeaderboard {
private TreeSet<Player> leaderboard = new TreeSet<>(
Comparator.comparingInt(Player::getScore).reversed()
.thenComparing(Player::getName)
);
public void addPlayer(Player player) {
leaderboard.add(player);
}
public List<Player> getTopPlayers(int count) {
return leaderboard.stream()
.limit(count)
.collect(Collectors.toList());
}
public Player getTopPlayer() {
return leaderboard.first();
}
public Set<Player> getPlayersInRange(int minScore, int maxScore) {
return leaderboard.subSet(
new Player("", minScore),
new Player("", maxScore + 1)
);
}
}
class Player {
private String name;
private int score;
// 构造方法、getter、setter等
}