Set 接口
我们发现接口中定义的方法都是Collection中直接继承的,因此,Set支持的功能其实也就和Collection中定义的差不多,只不过:
- 不允许出现重复元素
- 不支持随机访问(不允许通过下标访问)
public interface Set<E> extends Collection<E> {
// Set集合中基本都是从Collection直接继承过来的方法,只不过对这些方法有更加特殊的定义
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
//添加元素只有在当前Set集合中不存在此元素时才会成功,如果插入重复元素,那么会失败
boolean add(E e);
//这个同样是删除指定元素
boolean remove(Object o);
boolean containsAll(Collection<?> c);
//同样是只能插入那些不重复的元素
boolean addAll(Collection<? extends E> c);
boolean retainAll(Collection<?> c);
boolean removeAll(Collection<?> c);
void clear();
boolean equals(Object o);
int hashCode();
//这个方法我们同样会放到多线程中进行介绍
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT);
}
}
HashSet 类
底层就是采用哈希表实现的(我们在这里先不去探讨实现原理,因为底层实质上是借用的一个HashMap在实现,这个需要我们学习了Map之后再来讨论)我们可以非常高效的从HashSet中存取元素,我们先来测试一下它的特性:
public static void main(String[] args) {
Set<String> set = new HashSet<>();
System.out.println(set.add("AAA"));
System.out.println(set.add("AAA")); /// 重复插入会返回 false
System.out.println(set);
}
在Set接口中并没有定义支持指定下标位置访问的添加和删除操作,我们只能简单的删除Set中的某个对象:
public static void main(String[] args) {
Set<String> set = new HashSet<>();
System.out.println(set.add("AAA"));
System.out.println(set.remove("AAA"));
System.out.println(set);
}
LinkedHashSet 类
默认的 HashSet 是按照哈希值遍历, 而 LinkedHashSet 就是通过链表自动维护顺序,可以保证遍历顺序和插入顺序一致。
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<>();
set.addAll(Arrays.asList("A", "0", "-", "+"));
System.out.println(set);
}
TreeSet 类
一种可以自动维护集合内有序的集合类, 会在元素插入时对其排序:
public static void main(String[] args){
TreeSet<Integer> set = new TreeSet<>();
set.add(1);
set.add(3);
set.add(2);
System.out.println(set);
}
也可以自定义排序序列:
public static void main(String[] args) {
TreeSet<Integer> set = new TreeSet<>((a, b) -> b - a); //同样是一个Comparator
set.add(1);
set.add(3);
set.add(2);
System.out.println(set);
}