Set继承于Collection接口,是一个不允许出现重复元素且无序的集合,有hashset和treeSetl两大实现类
在判断重复元素的时候,Set集合会调用hashCode()和equals()方法来实现
HashSet是哈希表结构,主要利用HashMap的key来存储元素,计算插入元素的hashCode来获取元素在集合中的位置;
TreeSet是红黑数结构,每一个元素都是树中的一个节点,插入的元素都会进行排序;
Set集合框架结构:
set集合添加元素并使用迭代器迭代元素。
public class Demo4 { public static void main(String[] args) { //Set 集合存和取的顺序不一致。 Set hs = new HashSet(); hs.add("世界军事"); hs.add("兵器知识"); hs.add("舰船知识"); hs.add("汉和防务"); System.out.println(hs); // [舰船知识, 世界军事, 兵器知识, 汉和防务] Iterator it = hs.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } }
Set还提供了equals(Object o)和hashCode(),供其子类重写,以实现对集合中插入重复元素的处理;
public interface Set<E> extends Collection<E> {
A:添加功能
boolean add(E e);
boolean addAll(Collection<? extends E> c);
B:删除功能
boolean remove(Object o);
boolean removeAll(Collection<?> c);
void clear();
C:长度功能
int size();
D:判断功能
boolean isEmpty();
boolean contains(Object o);
boolean containsAll(Collection<?> c);
boolean retainAll(Collection<?> c);
E:获取Set集合的迭代器:
Iterator<E> iterator();
F:把集合转换成数组
Object[] toArray();
<T> T[] toArray(T[] a);
//判断元素是否重复,为子类提高重写方法
boolean equals(Object o);
int hashCode();
}
HashSet
接口 实现该接口可以使用增强for循环 ---| Collection 描述所有集合共性的接口 ---| List接口 可以有重复元素的集合 ---| ArrayList ---| LinkedList ---| Set接口 不可以有重复元素的集合 ---| HashSet 线程不安全,存取速度快。底层是以哈希表实现的。
(1)HashSet继承AbstractSet类,获得了Set接口大部分的实现,减少了实现此接口所需的工作,实际上是又继承了AbstractCollection类;
(2)HashSet实现了Set接口,获取Set接口的方法,可以自定义具体实现,也可以继承AbstractSet类中的实现;
(3)HashSet实现Cloneable,得到了clone()方法,可以实现克隆功能;
(4)HashSet实现Serializable,表示可以被序列化,通过序列化去传输,典型的应用就是hessian协议。
具有如下特点:
-
不允许出现重复因素;
-
允许插入Null值;
-
元素无序(添加顺序和遍历顺序不一致);
-
线程不安全,若2个线程同时操作HashSet,必须通过代码实现同步;
-
HashSet --> 是由HashMap维护的
无序的,不可重复底层结构: 哈希表(数组+链表+红黑树)
特点: 查询,增删效率较高
无序,去重
应用场景 : 存储数据由单个值决定的情况下,想要去重的情况下,适合使用HashSet
新增内容 : 无新增方法
- HashSet
- 由Hashmap维护的,无序的,不可重复的
- 底层结构:哈希表(数组+链表+红黑树)
- 特点:查询,增删效率较高,无序,可去重
- 应用场景:存储数据由单个值决定的情况下,想要去重的情况下,适合使用hashset
- 哈希表中hashcode与equals之间的关系(前提是重写hashcode与equals都是根据成员变量计算)equals相等hashcode一定相等,hashcode相等,equals不一定相等
- 哈希表存储自定义引用数据的去重:需要在数据的类型中重写equals与hashcode方法
实现根据内容(成员变量的值)进行比较和计算
元素的哈希值是通过元素的hashcode方法 来获取的, HashSet首先判断两个元素的哈希值,如果哈希值一样,接着会比较equals方法 如果 equls结果为true ,HashSet就视为同一个元素。如果equals 为false就不是同一个元素。
哈希值相同equals为false的元素是怎么存储呢,就是在同样的哈希值下顺延(可以认为哈希值相同的元素放在一个哈希桶中)。也就是哈希一样的存一列。
TreeSet
--> 是由TreeMap维护的
无序,去重
底层结构 : 红黑树(平衡二叉树)
特点 : 默认升序排序
新增方法 : 数据的大小比较相关的方法,因为红黑树结构中数据已经比较过大小,默认升序
思考: TreeSet集合中能够成功存储不同类型的数据?
使用TreeSet存储自定义的引用数据类型,如何是否去重(根据内容去重),实现默认升序排序?
它继承AbstractSet,实现NavigableSet, Cloneable, Serializable接口。
(1)与HashSet同理,TreeSet继承AbstractSet类,获得了Set集合基础实现操作;
(2)TreeSet实现NavigableSet接口,而NavigableSet又扩展了SortedSet接口。这两个接口主要定义了搜索元素的能力,例如给定某个元素,查找该集合中比给定元素大于、小于、等于的元素集合,或者比给定元素大于、小于、等于的元素个数;简单地说,实现NavigableSet接口使得TreeSet具备了元素搜索功能;
(3)TreeSet实现Cloneable接口,意味着它也可以被克隆;
(4)TreeSet实现了Serializable接口,可以被序列化,可以使用hessian协议来传输;
具有如下特点:
接口 实现该接口可以使用增强for循环
---| Collection 描述所有集合共性的接口
---| List接口 有序,可以重复,有角标的集合
---| ArrayList ---| LinkedList ---| Set接口 无序,不可以重复的集合
---| HashSet 线程不安全,存取速度快。底层是以hash表实现的。
---| TreeSet 红-黑树的数据结构,默认对元素进行自然排序(String)。
TreeSet<Double> tree = new TreeSet<>();
tree.add(3.3);
tree.add(1.1);
tree.add(2.2);
tree.add(4.4);
tree.add(5.5);
tree.add(5.5);
System.out.println(tree);
//测试新增 方法
System.out.println(tree.first());
System.out.println(tree.last());
System.out.println(tree.ceiling(2.1));
System.out.println(tree.floor(3.3));
TreeSet<String> tree2 = new TreeSet<>();
tree2.add("abc");
tree2.add("bc");
tree2.add("ab");
tree2.add("a");
tree2.add("b");
tree2.add("ab");
System.out.println(tree2);
比较器接口
----| Comparable compareTo(Object o) 元素自身具备比较性 ----| Comparator compare( Object o1, Object o2 ) 给容器传入比较器
一,让元素自身具备比较性。
也就是元素需要实现Comparable接口,覆盖compareTo 方法。
这种方式也作为元素的自然排序,也可称为默认排序。