java定义静态set集合_Java 集合系列之三:Set基本操作

1. Java Set

1. Java Set 重要观点

Java Set接口是Java Collections Framework的成员。

Set不允许出现重复元素-----------无重复

Set不保证集合中元素的顺序---------无序

Set允许包含值为null的元素,但最多只能有一个null元素。

Set支持泛型(类型的参数化),我们应尽可能使用它。将Generics与List一起使用将在运行时避免ClassCastException。

先去看Map,Set的实现类都是基于Map来实现的(如,HashSet是通过HashMap实现的,TreeSet是通过TreeMap实现的,LinkedHashSet是通过LinkedHashMap来实现的)。

2. Java Set类图

Java Set接口扩展了Collection接口。Collection接口 externs Iterable接口。

一些最常用的Set实现类是HashSet,LinkedHashSet,TreeSet,SortedSet,CopyOnWriteArraySet。

AbstractSet提供了Set接口的骨干实现,以减少实现List的工作量。

4a4c51dc33594ac554504ba8a28a3e42.png

3. Java Set 方法

boolean add(E e) //如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。

boolean addAll(Collection extends E> c) //如果 set 中没有指定 collection 中的所有元素,则将其添加到此 set 中(可选操作)。

void   clear() //移除此 set 中的所有元素(可选操作)。

boolean contains(Object o) //如果 set 包含指定的元素,则返回 true。

boolean containsAll(Collection> c) //如果此 set 包含指定 collection 的所有元素,则返回 true。

boolean equals(Object o) //比较指定对象与此 set 的相等性。

int    hashCode() //返回 set 的哈希码值。

boolean isEmpty() //如果 set 不包含元素,则返回 true。

Iterator iterator() //返回在此 set 中的元素上进行迭代的迭代器。

boolean remove(Object o) //如果 set 中存在指定的元素,则将其移除(可选操作)。

boolean removeAll(Collection> c) //移除 set 中那些包含在指定 collection 中的元素(可选操作)。

boolean retainAll(Collection> c) //仅保留 set 中那些包含在指定 collection 中的元素(可选操作)。

int    size() //返回 set 中的元素数(其容量)。

Object[] toArray() //返回一个包含 set 中所有元素的数组。

T[] toArray(T[] a) //返回一个包含此 set 中所有元素的数组;返回数组的运行时类型是指定数组的类型。

2. HashSet

1. HashSet 结构图

4c114fc476684eaeffa73f9f2db70557.png

HashSet,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null元素。!

HashSet继承了AbstractSet,实现了Cloneable和Serializable接口!

实现了Cloneable接口,即覆盖了函数clone(),实现浅拷贝。

实现了Serializable接口,支持序列化,能够通过序列化传输。

2. HashSet 重要特点

依赖于哈希表(实际上是一个 HashMap 实例)(哈希表+链表+红黑树),不可以存储相同元素(排重)

底层实现是一个HashMap(保存数据),实现Set接口。(HashSet中含有一个”HashMap类型的成员变量”map,HashSet的操作函数,实际上都是通过map实现的。)

非同步,线程不安全,存取速度快(同步封装Set s = Collections.synchronizedSet(new HashSet(...));)

默认初始容量为16。

加载因子为0.75:即当 元素个数 超过 容量长度的0.75倍 时,进行扩容

扩容增量:原容量的 1 倍,如 HashSet的容量为16,一次扩容后是容量为32

重写hashCode():HashSet集合排重时,需要判断两个对象是否相同,对象相同的判断可以通过hashCode值判断,所以需要重写hashCode()方法

重写equals():equals()方法是Object类中的方法,表示比较两个对象是否相等,若不重写相当于比较对象的地址, 所以我们可以尝试重写equals方法,检查是否排重。

会根据hashcode和equals来庞端是否是同一个对象,如果hashcode一样,并且equals返回true,则是同一个对象,不能重复存放。

fail-fast机制:HashSet通过iterator()返回的迭代器是fail-fast的。

两种遍历方法:Iterator【iterator.next()】,forEach【set.toArray();】

Set set = new HashSet();

set.add("first");

set.add("second");

set.add("three");//foreach

for(String string : set) {

System.out.println(string);

}//iterator

Iterator setIterator =set.iterator();while(setIterator.hasNext()) {

String string=(String) setIterator.next();

System.out.println(string);

}

3. TreeSet

1. TreeSet 结构图

a88cb750e188a952f4e4719bfd8a4e71.png

基于 TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator进行排序,具体取决于使用的构造方法。

TreeSet也不能存放重复对象,但是TreeSet会自动排序,如果存放的对象不能排序则会报错,所以存放的对象必须指定排序规则。排序规则包括自然排序和客户排序。

①自然排序:TreeSet要添加哪个对象就在哪个对象类上面实现java.lang.Comparable接口,并且重写comparaTo()方法,返回0则表示是同一个对象,否则为不同对象。

②客户排序:建立一个第三方类并实现java.util.Comparator接口。并重写方法。定义集合形式为TreeSet ts = new TreeSet(new 第三方类());

TreeSet继承了AbstractSet,实现了NavigableSet、Cloneable和Serializable接口!

继承于AbstractSet,AbstractSet实现了equals和hashcode方法。

实现了NavigableSet接口,意味着它支持一系列的导航方法。比如查找与指定目标最匹配项。

实现了Cloneable接口,即覆盖了函数clone(),实现浅拷贝。

实现了Serializable接口,支持序列化,能够通过序列化传输。

TreeSet是SortedSet接口的实现类

2. TreeSet 重要特点

依赖于TreeMap,TreeSet是基于TreeMap实现的。(红黑树)复杂度为O(log (n))

不可以存储相同元素(排重),自动排序。(有序集合)

TreeSet中不允许使用null元素!在添加的时候如果添加null,则会抛出NullPointerException异常。

TreeSet是非同步的方法【SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));】。

它的iterator 方法返回的迭代器是fail-fast的。

TreeSet不支持快速随机遍历,只能通过迭代器进行遍历! 两种遍历方法:Iterator【iterator.next()】,forEach【set.toArray();】

TreeSet中的元素支持2种排序方式:自然排序 或者 根据创建TreeSet 时提供的 Comparator 进行排序。这取决于使用的构造方法。

自然排序,重写compareTo方法:元素所属的类需要实现java.lang.Comparable接口,并重写compareTo方法。 compareTo方法除了可以进行排序外,还有排重的功能,但是必须在compareTo方法中对类中所有的属性值都进行判断,否则不比较那个属性,排重就会忽略哪个属性

定制排序,重写compare方法:元素需要通过java.util.Comparator接口(比较器)中的compare方法进行比较大小,并排序。 compare方法除了可以进行排序外,还有排重的功能,但是必须在compare方法中对类中所有的属性值都进行判断,否则不比较那个属性,排重就会忽略哪个属性

ps:Comparable中的compareTo()一个参数, Comparator中compare()两个参数,返回值都是int类型,如果返回0,表示两个比较元素相同,如果大于0 ,前面大于后面,如果小于0,前面小于后面。

3. HashSet vs TreeSet

HashSet是一个无序的集合,基于HashMap实现;TreeSet是一个有序的集合,基于TreeMap实现。

HashSet集合中允许有null元素,TreeSet集合中不允许有null元素。

HashSet和TreeSet都是非同步!在使用Iterator进行迭代的时候要注意fail-fast。

4. LinkedHashSet

1. LinkedHashSet 结构图

d536b4e6aa7f33edd507825565cdb3f0.png

LinkedHashSet类:LinkedHashSet正好介于HashSet和TreeSet之间,它也是一个hash表,但它同时维护了一个双链表来记录插入的顺序,基本方法的复杂度为O(1)。

当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。

2. LinkedHashSet 重要特点

继承自HashSet,与HashSet唯一的区别是LinkedHashSet内部使用的是LinkHashMap((哈希表+链表+红黑树)+双向链表)。

LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。

非同步,线程不安全,存取速度快(同步封装 Set s = Collections.synchronizedSet(new LinkedHashSet(...));)

其他同HashSet

维护插入顺序,LinkedHashSet使用LinkedHashMap对象来存储它的元素,插入到LinkedHashSet中的元素实际上是被当作LinkedHashMap的键保存起来的。LinkedHashMap的每一个键值对都是通过内部的静态类Entry实例化的。这个 Entry类继承了HashMap.Entry类。这个静态类增加了两个成员变量,before和after来维护LinkedHasMap元素的插入顺序。这两个成员变量分别指向前一个和后一个元素,这让LinkedHashMap也有类似双向链表的表现。

原文:https://www.cnblogs.com/haimishasha/p/10787932.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值