Java中的Set

Set接口的实现类

HashSet与LinkedHashSet

HashSet与LinkedHashSet的关系就如同HashMap和LinkedHashMap一样。HashSet内部保存了一个HashMap对象来存储。

set-1

利用Map对象,存入Map的k-v中value对象始终是同一个对象(就是上图中声明的private static final Object PRESENT = new Object()对象)。从而Set只需要关心key对象即可。

set-2

  1. 很显然,Set存储的key集合是无序的。默认大小就是hashmap的默认大小16。每一次扩容也是2的倍数递增。
  2. 上面的第2张图示HashSet的构造方法之一,可以看到是生成了一个LinkedHashMap,下面的LinkedHashSet就是调用这个构造方法来生成的。

set-3

LinkedHashSet则是继承自HashSet,并且在生成的时候,调用了父类HashSet的对应的方法,从而维护了一个LinkedHashMap对象,就实现了元素有序。

  1. 上图可以看到,LinkedHashSet构造方法都是调用了父类中含有dummy参数的那一个构造方法(也就是维护LinkedHashMap的那一个!)

TreeSet

显然,TreeSet内部也是维护了TreeMap来存储元素。只保存key,而value值都是同一个Object对象。

set-4

  1. Set对于的并发类有:java.util.concurrent.CopyOnWriteArraySet类和Collections.synchronizedSet(Set set)所修饰的类。
  2. 这2个并发类的区别和List对应的并发类的区别是一致的。前者是写时复制,只保证数据最终的一致性,而不保证数据实时的一致性。后者借助synchronized关键字修饰代码块,尽量减小了锁的粒度。

Set类图

set-5

### JavaSet 的差集操作 在 Java 编程中,`Set` 是一种不允许重复元素的数据结构。为了计算两个 `Set` 的差集而不影响原始集合,在 Java8 及更高版本中有多种实现方式。 #### 方法一:使用 Stream API 和 filter() 函数 这种方法利用了 Java 8 引入的强大流处理功能。可以创建一个新的集合用于保存结果,从而保持原集合不变[^3]: ```java import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { // 创建第一个集合 Set<Integer> setA = new HashSet<>(); setA.add(1); setA.add(2); setA.add(3); // 创建第二个集合 Set<Integer> setB = new HashSet<>(); setB.add(2); setB.add(3); setB.add(4); // 计算 A-B 的差集并打印出来 Set<Integer> differenceAB = setA.stream() .filter(element -> !setB.contains(element)) .collect(Collectors.toSet()); System.out.println(differenceAB); // 输出 [1] } } ``` #### 方法二:复制其中一个集合再移除公共项 此方法先复制一个待减去的集合副本,之后调用其 `removeAll()` 方法去除另一个集合中存在的所有元素。这种方式同样不会改变输入参数所指向的对象状态[^2]: ```java import java.util.HashSet; import java.util.Set; public class Main { public static void main(String[] args) { // 定义两个初始集合 Set<String> originalSet = new HashSet<>(); originalSet.add("apple"); originalSet.add("banana"); Set<String> itemsToRemove = new HashSet<>(); itemsToRemove.add("orange"); itemsToRemove.add("banana"); // 复制要被修改的集合以防破坏原有数据 Set<String> resultDifference = new HashSet<>(originalSet); // 执行差运算 resultDifference.removeAll(itemsToRemove); System.out.println(resultDifference); // 输出 [apple] } } ``` 这两种方案都可以有效地完成两组不同对象之间的差异比较工作,并且都遵循了不更改传入参数的原则。具体选择哪种取决于个人偏好以及项目上下文中其他因素的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值