Set 、HashSet、TreeSet、LinkedHashSet、EnumSet
Set
- 底层原理:
java中set及其子类都是由对应的Map实现的,如HashSet由HashMap实现,TreeSet由TreeMap实现等等。
从上面的代码可以看出,TreeSet的add函数,底层是TreeMap的put(),key值是TreeSet的自己的key,而value是一个静态常量对象present。
常见的方法:
| 1 | add( ) 向集合中添加元素 |
| 2 | clear( ) 去掉集合中所有的元素 |
| 3 | contains( ) 判断集合中是否包含某一个元素 |
| 4 | isEmpty( ) 判断集合是否为空 |
| 5 | iterator( ) 主要用于递归集合,返回一个Iterator()对象 |
| 6 | remove( ) 从集合中去掉特定的对象 |
| 7 | size( ) 返回集合的大小 |
HashSet
- 底层实现:HashMap
- 底层数据结构是:哈希表
- 是否有序:无序:有序指的是表中存储的位置顺序和插入顺序是否一致,若一致,则为有序。
- 是否排序:否
- 是否线程安全:否
- 能否存入重复元素:不能
- 如何保证元素的唯一性:HashCode()与equals():首先把先加入元素的HashCode值与已有元素的进行比较,如果不同,直接add,如果相同,则使用equals()比较值是否相等,不相等,则add,相等则丢弃。
- 能否存入空元素:能,但是只能存入一个null
- 存储内容:仅限对象:下面的代码插入的也不是基本类型的,是Integer类型的,所以存储的是对象。
- 遍历方式:Iterator或者for-each或者直接输出。
代码为证:
输出结果:
1--18--6--10--12-- for-each:1--18--6--10--12-- [1, 18, 6, 10, 12]TreeSet
- 底层实现:TreeMap
- 底层数据结构:红黑树
- 是否排序:是
- 是否有序:否
- 是否线程安全:否
- 能否存入重复元素:不能
- 能否存入null元素:不能:插入null时会报NullPointerException
- 如何保证元素排序:自然排序和比较器排序
- 如何保证元素唯一:根据比较的返回值是否是0来决定
- 遍历方式:Iterator或者for-each或者直接输出。
有代码为证:
注意:当使用自定义的类时,需要重写排序规则,否则会抛出一个异常:java.lang.ClassCastException,因为我们没有指定比较规则。可参考:
https://www.cnblogs.com/yzssoft/p/7127894.html
运行结果:
TreeSet的数字测试: 0--4--5--6--10--12--13-- TreeSet的字符串测试: TreeSet的当前大小为:6 --apple--book--cook--delete--desk--//这里""是第一个输出的LinkedHashSet
- 底层实现:使用LinkedHashMap来保存所有元素,通过计算HashCode值来确保元素的唯一性。
- 底层数据结构:双向链表
- 是否有序:是FIFO
- 是否排序:否
- 是否线程安全:否
- 能否存入重复元素:不能
- 能否存入null:能:即使同时有多个null值存入,也不会报错,但是输出时只有最先存入的null值输出(毕竟也是通过hashCode值来判断存储的)。
- 遍历方式:Iterator或者for-each或者直接输出。
代码为证:
运行结果:
LinkedHashSet的数字测试: LinkedHashSet的当前大小为:8 10--12--null--5--13--4--6--0-- LinkedHashSet的字符串测试: LinkedHashSet的当前大小为:14 10--12--null--5--13--4--6--0--apple--delete--book--cook----desk--EnumSet
- 底层数据结构:位运算:EnumSet在内部以位向量的形式存储,这种存储形式非常紧凑、高效,因此EnumSet对象占用内存很小,而且运行效率很好。尤其是进行批量操作(如调用containsAll()和retainAll()方法)时,如果其参数也是EnumSet集合,则该批量操作的执行速度也非常快。
- EnumSet是抽象类,只能通过静态工厂方法构造EnumSet对象:EnumSet类没有暴露任何构造器来创建该类的实例,程序应该通过它提供的类方法来创建EnumSet对象
- 是否允许null元素:不允许:试图插入 null 元素将抛出 NullPointerException。但是,
试图测试是否出现 null 元素或移除 null 元素将不会抛出异常(而且EnumSet类中也不允许有null) - 是否线程安全:否
- 能否存入重复元素:否(首先枚举类里就不允许有重复的元素)
- 是否有序:有序
代码在下:
运行结果:
es:[a1, a2, a3, a4] es2[a3] es3:[a1, a3] es4:[a2, a3, a4] es5:[a1] es6:a2--a3--a4--另附一篇参考TreeSet(对自定义的类如何使用TreeSet:需要重写Hashcode和equale方法,因为TreeSet中的存放的对象必须能排序,否则会报错。)
package Set;import java.util.Set; import java.util.TreeSet;class Student1 implements Comparable<Student1>{int id;public Student1(int id) {this.id = id;}@Overridepublic String toString() {return this.id+"";}@Overridepublic int hashCode() {return this.id;}@Overridepublic boolean equals(Object obj) {if (obj instanceof Student1){Student1 stu = (Student1) obj;if (stu.id == this.id)return true;}return false;}public int compareTo(Student1 o) {return (this.id-o.id);} }public class Tree_Set {public static void main(String[] args) {Set<Student1> set = new TreeSet<Student1>();Student1 s1 = new Student1(5);Student1 s2 = new Student1(1);Student1 s3 = new Student1(2);Student1 s4 = new Student1(4);Student1 s5 = new Student1(3);set.add(s1);set.add(s2);set.add(s3);set.add(s4);set.add(s5);for (Student1 s : set) {System.out.println(s);}}}LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按照元素插入的次序显示。
package Set;import java.util.Iterator;public class LinkedHashSet {public static void main(String[] args) {java.util.LinkedHashSet<String> books = new java.util.LinkedHashSet<String>();books.add("Book1");books.add("Book2");books.add("Book1");System.out.println(books);//删除 Book1books.remove("Book1");//重新添加 Book1books.add("Book1");System.out.println(books);for(Iterator<String> iter = books.iterator(); iter.hasNext();){Object value = iter.next();System.out.println(value);}} }运行结果:
[Book1, Book2] [Book2, Book1] Book2 Book1因为LinkedHashSet是HashSet的子类,因此它不允许集合元素重复。所以第二个books.add("Book1");没有添加进去。
Set集合类应用场景:
SortedSet s = Collections.synchronizedSortedSet(new TreeSet(…));
总结
以上是生活随笔为你收集整理的Set 、HashSet、TreeSet、LinkedHashSet、EnumSet的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: java基础,没事常看看(一)类、对象、
- 下一篇: Map、HashMap、TreeMap、