ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# Set接口 集合(数学意义)结构数据唯一、数据存储无序,没有跟索引相关的方法,不能用普通的for循环遍历,必须使用迭代器遍历或者增强for循环遍历。 API: ~~~  public interface Set<E> extends Collection<E> {      // 集合中添加元素      boolean add(E e);            // 移除集合中的元素      boolean remove(Object o);      // 清空集合      void clear();            // 是否包含某个元素      boolean contains(Object o);      // 是否为空      boolean isEmpty();            // 返回遍历集合的迭代器      Iterator<E> iterator();            // 集合中元素个数      int size();        } ~~~ &nbsp; Set接口的实现类: ****** ## HashSet 使用HashMap作为底层数据结构存放数据,HashSet中将要存放的数据作为HashMap的Key,HashMap中的value为一个在HashSet中定义的共享的Object对象。 存放数据的过程需要先计算hash值,在根据hash值和一个表达式计算元素在数组中存放的位置,这和HashMap是一致的。保存在HashSet中的对象一定要重写hashcode和equals方法。 源码: ~~~  public class HashSet<E> extends AbstractSet<E>      implements Set<E>, Cloneable, java.io.Serializable {      // HashMap保存数据      private transient HashMap<E,Object> map;      // HashMap中Entry共享的value对象      private static final Object PRESENT = new Object();            // ---------------------构造方法------------------------      public HashSet() {          // 初始化容量为16,负载因子为0.75          map = new HashMap<>();     }      public HashSet(int initialCapacity, float loadFactor) {          // 指定初始化容量和负载因子          map = new HashMap<>(initialCapacity, loadFactor);     }      // 使用LinkedHashMap作为实现类      // dummy仅仅只是来作为和其他构造方法的重载区别,没有其他意义      HashSet(int initialCapacity, float loadFactor, boolean dummy) {          map = new LinkedHashMap<>(initialCapacity, loadFactor);     }            //-----------------------操作-------------------------      // 添加操作      public boolean add(E e) {          // HashMap第一次添加的时候返回null,如果是返回null则证明是添加成功的操作          return map.put(e, PRESENT)==null;     }      // 移除操作,      public boolean remove(Object o) {          return map.remove(o)==PRESENT;     }      // HashSet中没有获取元素的操作,只能通过迭代的方式来遍历数据      public Iterator<E> iterator() {          return map.keySet().iterator();     }      // 其他操作也基本都是通过HashMap来操作的  } ~~~ &nbsp; ## TreeSet 使用TreeSet保存的数据唯一、按照升序进行排序,对TreeSet进行遍历也是按照排序后的顺序进行遍历的。由于其需要对数据进行排序,因此对于自定义的引用类型需要实现内部比较器或者外部比较器。否则的话会在创建阶段就抛出错误。 底层使用TreeMap,使用共享的PRESENT作为value值。 &nbsp; ## LinkedHashSet 按照输入顺序进行输出。在HashSet的基础上多了一个总链表,将放入的元素串在一起,方便有序的遍历。