Set
java.util.Set 接口和 java.util.List 接口一样,同样继承自 Collection 接口,它与 Collection 接口中的方法基本一致,并没有对 Collection 接口进行功能上的扩充,只是比 Collection 接口更加严格了。
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(); }
与 List 接口不同的是, Set 接口中元素无序,并且都会以某种规则(提供equals(Object o)和hashCode(),供其子类重写)保证存入的元素不出现重复。
Set 集合常用的子类: java.util.HashSet 、 java.util.LinkedHashSet
Set集合取出元素的方式可以采用:迭代器、增强for。
HashSet
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable
HashSet 是根据对象的哈希值来确定元素在集合中的存储位置,存取、查找效率高。
HashSet 底层的实现是一个 java.util.HashMap(即存储数据的结构是——哈希表),利用HashMap键(key)来存储元素,计算插入元素的hashCode来获取元素在集合中的位置;。
而保证元素唯一性的方式依赖于: hashCode 与 equals 方法。
哈希表在Map笔记中具体介绍。
HashSet存储自定义类型元素
给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方 式,才能保证HashSet集合中的对象唯一
HashSet方法
public class HashSetTest { public static void main(String[] agrs){ //创建HashSet集合: Set<String> hashSet = new HashSet<String>(); System.out.println("HashSet初始容量大小:"+hashSet.size()); //元素添加: hashSet.add("Hello"); hashSet.add("World"); hashSet.add("!"); System.out.println("HashSet容量大小:"+hashSet.size()); // 迭代器遍历: Iterator<String> iterator = hashSet.iterator(); while (iterator.hasNext()){ String str = iterator.next(); System.out.println(str); } // 增强for循环 for(String str:hashSet){ if("World".equals(str)){ System.out.println("查找的元素:"+str); } System.out.println(str); } // 元素删除: hashSet.remove("World"); System.out.println("HashSet元素大小:" + hashSet.size()); hashSet.clear(); System.out.println("HashSet元素大小:" + hashSet.size()); //集合判断: boolean isEmpty = hashSet.isEmpty(); System.out.println("HashSet是否为空:" + isEmpty); boolean isContains = hashSet.contains("hello"); System.out.println("HashSet是否为空:" + isContains); } }
LinkedHashSet
public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, Serializable
java.util.LinkedHashSet ,它是链表和哈希表组合的一个数据存储结构,元素唯一且有序
TreeSet
public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, Serializable
其底层实现为:红黑树(特殊的二叉查找树)
TreeSet具有排序功能,分为自然排序(123456)和自定义排序两类,默认是自然排序
HashSet 和 TreeSet 特点
| HashSet | TreeSet |
| 元素不重复 | 元素不重复 |
| 元素无序(存取顺序不一样) | 元素有序(会对插入的元素进行排序) |
| 允许插入null值 | 允许插入null值 |
| 线程不安全(多线程操作,需手动实现同步) | 线程不安全(多线程操作,需手动实现同步) |
TreeSet方法
public class TreeSetTest { public static void main(String[] agrs){ TreeSet<String> treeSet = new TreeSet<String>(); System.out.println("TreeSet初始化容量大小:"+treeSet.size()); //元素添加: treeSet.add("hello"); treeSet.add("world"); treeSet.add("flower"); treeSet.add("water"); treeSet.add("grass"); System.out.println("TreeSet容量大小:" + treeSet.size()); System.out.println("TreeSet元素顺序为:" + treeSet.toString()); //增加for循环遍历: for(String str:treeSet){ System.out.println("遍历元素:"+str); } //迭代器遍历:升序 Iterator<String> iteratorAesc = treeSet.iterator(); while(iteratorAesc.hasNext()){ String str = iteratorAesc.next(); System.out.println("遍历元素升序:"+str); } //迭代器遍历:降序 Iterator<String> iteratorDesc = treeSet.descendingIterator(); while(iteratorDesc.hasNext()){ String str = iteratorDesc.next(); System.out.println("遍历元素降序:"+str); } //元素获取:实现NavigableSet接口 String firstEle = treeSet.first();//获取TreeSet头节点: System.out.println("TreeSet头节点为:" + firstEle); // 获取指定元素之前的所有元素集合:(不包含指定元素) SortedSet<String> headSet = treeSet.headSet("flower"); System.out.println("flower节点之前的元素为:"+headSet.toString()); //获取给定元素之间的集合:(包头,不包尾) SortedSet subSet = treeSet.subSet("1","world"); System.out.println("1--jiaboan之间节点元素为:"+subSet.toString()); //集合判断: boolean isEmpty = treeSet.isEmpty(); System.out.println("TreeSet是否为空:"+isEmpty); boolean isContain = treeSet.contains("light"); System.out.println("TreeSet是否包含light元素:"+isContain); //元素删除: boolean removeG = treeSet.remove("grass"); System.out.println("grass元素是否被删除:"+removeG); //删除集合中不存在的元素,返回false boolean removeL = treeSet.remove("light"); System.out.println("light元素是否被删除:"+removeL); //删除并返回第一个元素:如果set集合不存在元素,则返回null String pollFirst = treeSet.pollFirst(); System.out.println("删除的第一个元素:"+pollFirst); //删除并返回最后一个元素:如果set集合不存在元素,则返回null String pollLast = treeSet.pollLast(); System.out.println("删除的最后一个元素:"+pollLast); treeSet.clear();//清空集合: } }
TreeSet自然排序
使用String、Integer等包装类型(JDK的内置对象),数据可以通过add方法添加到TreeSet集合中。
TreeSet自定义排序
使用自定义类型时,add方法会报错,抛出异常:
Exception in thread "main" java.lang.ClassCastException: com.**.ClassName cannot be cast to java.lang.Comparable
是因为,TreeSet的add()方法调用的时TreeMap的put()方法,
在put方法中会调用到compare(key, key)方法,进行key大小的比较(排序在此时实现)
在比较的时候,会将传入的key进行类型强转,自定义类如果没有实现Comparable接口,就会如上。
Comparable和Comparator单独说明。
参考引用:
https://www.jianshu.com/p/d6cff3517688
posted on
浙公网安备 33010602011771号