Set
接口java.util.Set
不包含重复元素的集合、不能保证存储的顺序、只允许有一个 null
。
public interface Set
extends Collection
抽象方法,都是继承自 java.util.Collection
接口。
Set
集合的实现类有很多,在此我们重点了解 HashSet
、 TreeSet
、 LinkedHashSet
。
不允许使用索引:Set
集合中没有提供使用索引来访问元素的方法,因为元素没有固定的顺序。
非同步:不是线程安全的。
HashSet
:基于哈希表实现,具有O(1)的平均时间复杂度的查找、插入和删除操作。
TreeSet
:基于红黑树实现,具有排序功能,元素会按照自然排序或指定的比较器顺序进行排序。
LinkedHashSet
:基于哈希表和链表实现,保留元素的插入顺序,具有O(1)的平均时间复杂度的查找、插入和删除操作。
public class HashSet
extends AbstractSet
implements Set, Cloneable, Serializable
实现了 Set
接口,底层实现是 HashMap
。不保证迭代顺序,允许 null
元素。
HashSet() | 构造一个新的空集合; 底层实现HashMap实例具有默认初始容量(16)和负载因子(0.75)。 |
---|---|
HashSet(Collection c) | 构造一个包含指定集合中的元素的新集合 |
HashSet(int initialCapacity) | 构造一个新的空集合,默认初始容量(initialCapacity)和负载因子(0.75) |
HashSet(int initialCapacity, float loadFactor) | 构造一个新的空集合; 底层HashMap实例具有指定的初始容量和指定的负载因子 |
TreeSet
public class TreeSet
extends AbstractSet
implements NavigableSet, Cloneable, Serializable
就是说a.compareTo(b) == 0,如果是 true ,那么 add(a) 之后的 add(b) 将会返回 false ,也就是添加失败。
ceiling(E e) | E | 返回此集合中大于或等于给定元素的最小元素,如果没有这样的元素,则返回null。 |
---|---|---|
floor(E e) | E | 返回此集合中小于或等于给定元素的最大元素,如果没有这样的元素,则返回null。 |
– | – | – |
headSet(E toElement) | SortedSet<[E]> | 返回此集合中元素严格小于toElement的部分的视图。 |
– | – | – |
tailSet(E fromElement) | SortedSet<[E]> | 返回此集合中元素严格大于或等于fromElement的部分的视图。 |
– | – | – |
higher(e) | E | 返回此集合中严格大于给定元素的最小元素,如果没有这样的元素,则返回null |
– | – | – |
higher(e) | lower(e) | 返回此集合中严格小于给定元素的最大元素,如果没有这样的元素,则返回null。 |
TreeSet set = new TreeSet(List.of("null", "a", "a", "b", "c", "e", "f",
"g"));
System.out.println(set); // [a, b, c, e, f, g, null]
// 返回此集合中大于或等于给定元素的最小元素,如果没有这样的元素,则返回null。
String ceiling = set.ceiling("d");
System.out.println(ceiling);// e
// 返回当前在此集合中的第一个(最低的)元素。
String first = set.first();
System.out.println(first); // a
// 返回此集合中小于或等于给定元素的最大元素,如果没有这样的元素,则返回null。
String floor = set.floor("d");
System.out.println(floor); // c
// 返回此集合中元素严格小于toElement的部分的视图。
SortedSet headSet = set.headSet("c");
System.out.println(headSet); // a, b
// 返回此集合中严格大于给定元素的最小元素,如果没有这样的元素,则返回null。
String higher = set.higher("c");
System.out.println(higher); // e
// 返回此集合中元素严格大于或等于fromElement的部分的视图。
SortedSet tailSet = set.tailSet("c");
System.out.println(tailSet); // c, e, f, g, null
// 迭代
for (Object obj : set){
System.out.println(obj);
}
LinkedHashSet
public class LinkedHashSet
extends HashSet
implements Set, Cloneable, java.io.Serializable
Iterator
接口Iterator接口
概述Iterator接口表示对集合进行迭代的迭代器。Iterator接口为集合而生,专门实现集合的遍历。主要有两个方法:
package collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* 创建一个Map,完成以下操作:
* 将我国省份和其简称存到 Map 集合中
* 将省份名称中包含"江"的省份从集合中删除
* 遍历输出集合元素
*/
public class Basic {
public static void main(String[] args) {
Map map=new HashMap();
map.put("北京", "京");
map.put("上海", "沪");
map.put("天津", "津");
map.put("重庆", "渝");
map.put("河北", "冀");
map.put("山西", "晋");
map.put("辽宁", "辽");
map.put("吉林", "吉");
map.put("黑龙江", "黑");
map.put("江苏", "苏");
map.put("浙江", "浙");
map.put("安徽", "皖");
map.put("福建", "闽");
map.put("江西", "赣");
map.put("山东", "鲁");
map.put("河南", "豫");
map.put("湖北", "鄂");
map.put("湖南", "湘");
map.put("广东", "粤");
map.put("海南", "琼");
map.put("四川", "川");
map.put("贵州", "黔");
map.put("云南", "滇");
map.put("陕西", "陕");
map.put("甘肃", "甘");
map.put("青海", "青");
map.put("台湾", "台");
map.put("内蒙古", "蒙");
map.put("广西", "桂");
map.put("西藏", "藏");
map.put("宁夏", "宁");
map.put("新疆", "新");
map.put("香港", "港");
map.put("澳门", "澳");
System.out.println(map.size());
//将省份名称中包含"江"的省份从集合中删除
Set> entries = map.entrySet();
Iterator> iterator = entries.iterator();
while (iterator.hasNext()){
Map.Entry next = iterator.next();
if (next.getKey().contains("江")){
iterator.remove();
}
}
//遍历
for (String key:map.keySet()) {
System.out.println(key);
}
System.out.println(map.size());
}
}
Map
接口Map
接口不是 Collection
的子接口,使用键、值映射表来存储。
public interface Map
`JDK9` 提供了创建不可修改 Map 对象的方法:
1. Map.of
2. Map.ofEntries
3. Map.copyOf
Map
的实现类较多,在此我们关注 HashMap
、 TreeMap
、 HashTable
、 LinkedHashMap
TreeMap
public class TreeMap
extends AbstractMap
implements NavigableMap, Cloneable, Serializable
AbstractMap
,一个红黑树基于 NavigableMap
实现key
不能存 null
,但是 value
可以存 null
key
必须是可比较的 (实现Comparable
接口,传递一个 Comparator
比较器)HashTable
public class Hashtable
extends Dictionary
implements Map, Cloneable, Serializable
public synchronized V put(K key, V value) {
// 值不能为 null
if (value == null) {
throw new NullPointerException();
}
// 确认 key 不在 hashtable 中存在
Entry tab[] = table;
// 计算 key 的 hash
int hash = key.hashCode();
// 找 key 应在存放在 数组中的位置
int index = (hash & 0x7FFFFFFF) % tab.length;
// index 位置的元素的 key 和 当前的 key 不一样
@SuppressWarnings("unchecked")
Entry entry = (Entry)tab[index];
for(; entry != null ; entry = entry.next) {
// 判断 key 是否相同
if ((entry.hash == hash) && entry.key.equals(key)) {
// 当 key 一样时,替换值
V old = entry.value;
entry.value = value;
return old;
}
}
// 当 key 在 hashtable 中不存在时,添加
addEntry(hash, key, value, index);
return null;
}
private void addEntry(int hash, K key, V value, int index) {
Entry tab[] = table;
// 判断是否需要 "扩容"
if (count >= threshold) {
// 对数组进行扩容 (2n + 1),将原有元素重新计算 hash
rehash();
tab = table;
// 将当前的 key 也重新计算 hash
hash = key.hashCode();
index = (hash & 0x7FFFFFFF) % tab.length;
}
// 原来数组中的 entry 对象
@SuppressWarnings("unchecked")
Entry e = (Entry) tab[index];
// 创建一个 新的 entry 对象, 放到 数组中
tab[index] = new Entry<>(hash, key, value, e);
// 元素个数 +1
count++;
// 修改次数 +1
modCount++;
}