目录
一, 搜索
1,传统搜索
2,Map和Set模型
二, Map的使用
1,Map接口的继承及实现图
2,Map接口的使用
3,TreeMap和HashMap的使用和对比
1,TreeMap
代码示例
map中插入的数据按照key进行排序
map中插入的数据必须具有可比较性(或者实现了比较器相关接口)
map中插入的值必须是唯一的,否则会进行覆盖
通过Set> entrySet() 方法对map中的键值对进行遍历
将Map中的value全部分离出来存放在Collection中
2,HashMap
代码示例
3,TreeMap和HashMap的对比
三, Set的使用
1,Set接口的继承及实现图
2,Set接口的使用
3,TreeSet和HashSet的使用和对比
1,TreeSet
代码示例
Set存入的Key必须是唯一的,存入重复的Key会自动去重
Set中不能插入为null的数据,否则会报空指针异常的错误
Set中插入的Key必须具有可比较性
2,HashSet
四, 总结
这两种排序比较适合静态类型的查找(给定区间内的元素进行查找),一般不会对区间上的序列进行插入和删除了,而现实中的查找比如:
这三种在查找时进行一些插入和删除的操作称为动态查找,上述的直接遍历和二分查找的方式就不太适合了,本篇博客介绍的Map和Set集合就是一种专门用来动态查找的集合容器.
一般把搜索的数据称为关键字(Key),和关键字对应的称为值(Value),将其称为Key-Value的键值对,所有模型有两种:
Map中存储的就是Key-Value的键值对,Set中只存储了Key
Map是一个接口,该接口没有继承自Collection,该类中存储的是
方法 | 解释 |
V get (Object key)
|
返回 key 对应的 value
|
V getOrDefault (Object key, V defaultValue)
|
返回 key 对应的 value , key 不存在,返回默认值
|
V put (K key, V value)
|
设置 key 对应的 value
|
V remove (Object key)
|
删除 key 对应的映射关系
|
Set |
返回所有 key 的不重复集合
|
Collection |
返回所有 value 的可重复集合
|
Set |
返回所有的 key-value 映射关系
|
boolean containsKey (Object key)
|
判断是否包含 key
|
boolean containsValue (Object value)
|
判断是否包含 value
|
注意:
Map接口没有继承Iterable接口,所以使用Map的对象不能直接进行遍历,需要先将其转换成Set对象再进行遍历,Map也提供了相应的方法对这种集合做特殊处理,就是Set
方法 | 解释 |
K getKey ()
|
返回 entry 中的 key
|
V getValue ()
|
返回 entry 中的 value
|
V setValue(V value)
|
将键值对中的 value 替换为指定 value
|
小结:
TreeMap的底层是红黑树(可以把它想象成比较复杂,性能更加优秀的搜索树),我们联想二叉搜索树的一些性能就可以理解TreeMap的一些性能了:
public static void main(String[] args) {
Map map = new TreeMap<>();
map.put("hello",3);
map.put("abc",4);
System.out.println(map);
}
//定义一个Student类 不实现比较器接口
class Student {
}
public static void main(String[] args) {
Map map = new TreeMap<>();
map.put(new Student(),3);
}
public static void main(String[] args) {
Map map = new TreeMap<>();
map.put("hello",3);
map.put("hello",4);
System.out.println(map);
}
public static void main(String[] args) {
Map map = new TreeMap<>();
map.put("hello",3);
map.put("abc",4);
map.put("def",2);
Set> entries = map.entrySet();
for (Map.Entry x: entries) {
System.out.println("key: " + x.getKey() + " 出现了: " + x.getValue() + "次!");
}
}
public static void main(String[] args) {
Map map = new TreeMap<>();
map.put("hello",3);
map.put("abc",4);
map.put("def",2);
Collection values = map.values();
System.out.println(values);
}
HashMap的底层是一个哈希桶(数组+链表/红黑树)的结构,查询的时间复杂度是O(1),所以一般HashMap的效率比较高,由于HashMap这个类并没有实现SortedMap这个接口,所以不要求插入的数据中的Key具有可比较性
HashMap和TreeMap大部分的方法相同,可以参照TreeMap的代码进行练习,这里只演示HashMap可以插入不需要具有可比较性的数据的代码
class Student {
}
public static void main(String[] args) {
Map map = new HashMap<>();
map.put(new Student(),1);
map.put(new Student(),2);
System.out.println(map);
}
Map 底层结构
|
TreeMap
|
HashMap
|
底层结构
|
红黑树
|
哈希桶
|
插入 / 删除 / 查找时间
复杂度
|
O(logN) | O(1) |
是否有序
|
关于 Key 有序
|
无序
|
线程安全
|
不安全
|
不安全 |
插入 / 删除 / 查找区别
|
需要进行元素比较
|
通过哈希函数计算哈希地址
|
比较与覆写
|
key 必须能够比较,否则会抛出 ClassCastException异常
|
自定义类型需要覆写 equals 和 hashCode方法
|
应用场景
|
需要 Key 有序场景下
|
Key 是否有序不关心,需要更高的时间性能
|
Set与Map主要的不同有两点:Set是继承自Collection的接口类,Set中只存储了Key
方法 | 解释 |
boolean add (E e)
|
添加元素,但重复元素不会被添加成功
|
void clear ()
|
清空集合
|
boolean contains (Object o)
|
判断 o 是否在集合中
|
Iterator |
返回迭代器
|
boolean remove (Object o)
|
删除集合中的 o
|
int size()
|
返回 set 中元素的个数
|
boolean isEmpty()
|
检测 set 是否为空,空返回 true ,否则返回 false
|
Object[] toArray()
|
将 set 中的元素转换为数组返回
|
boolean containsAll(Collection> c)
|
集合 c 中的元素是否在 set 中全部存在,是返回 true ,否则返回false
|
boolean addAll(Collection extends
E> c)
|
将集合 c 中的元素添加到 set 中,可以达到去重的效果
|
小结:
TreeSet的底层是红黑树(可以把它想象成比较复杂,性能更加优秀的搜索树),我们联想二叉搜索树的一些性能就可以理解TreeSet的一些性能了:
public static void main(String[] args) {
Set set = new TreeSet<>();
set.add("hello");
set.add("abc");
set.add("abc");
System.out.println(set);
}
public static void main(String[] args) {
Set set = new TreeSet<>();
set.add(null);
System.out.println(set);
}
//定义一个Student类 该类不实现任何比较器接口
class Student {
}
public static void main(String[] args) {
Set set = new TreeSet<>();
set.add(new Student());
System.out.println(set);
}
HashSet和TreeSet大部分的方法相同,可以参照TreeMap的代码进行练习,这里只演示HashMap可以插入不需要具有可比较性的数据的代码
//定义一个Student类 该类不实现任何比较器接口
class Student {
}
public static void main(String[] args) {
Set set = new HashSet<>();
set.add(new Student());
System.out.println(set);
}
Set和Map使用场景分析:
Set:存储的Key没有其对应的映射关系,且需要对数据进行去重
Map:存储的数据之间存在某种映射关系