目录
1.搜索
1.1 概念
1.2 模型
2.Map的使用
2.1 Map说明
2.2 Map.Entry说明,v>
2.3 Map的常见方法
2.3.1 V put(K key, V value)
2.3.2 V get(Object key)
2.3.3 V getOrDefault(Object key, V defaultValue)
2.3.4 Set keySet() Collection values()
2.3.5 Set> entrySet()
3. Set的说明
1.搜索
1.1 概念
Map和Set是一种专门用于搜索的容器或者数据结构,搜索的效率与具体的实例化子类有关
常见的搜索方法
1.遍历,时间复杂度是O(N),元素较多时,搜索效率很低
2.二分查找,时间复杂度是O(),但是要求搜索之前序列有序
这两种都是静态类型的查找,一般不会进行插入或者删除操作,如果在查找时进行一些插入和删除操作,那么这两种方式就不适合动态查找了.Map和Set是适合动态查找的集合容器
1.2 模型
一般情况下把搜索的关键字称为key,和关键字对应的值称为value.合起来称为key-value键值对
分为两种模型
1.纯key模型
<单词>
2.key-value模型
<单词,单词出现的次数>
Map中存储了key-value的键值对,Set中存储了key
2.Map的使用
2.1 Map说明
Map是一个接口类,该类没有继承自Collection,该类存储的是<K,V>结构的键值对,并且K是唯一的,不能重复
2.2 Map.Entry<K,V>说明
Map.Entry<K,V>是Map内部实现的用来存放<key,value>键值对映射关系的内部类,,该类主要提供了<key,value>的获取,value的设置以及key的比较方式
方法 | 说明 |
---|---|
K getKey() | 返回 entry 中的 key |
V getValue() | 返回 entry 中的 value |
V setValue(V value) | 将键值对中的value替换为指定value |
2.3 Map的常见方法
我们使用TreeMap实例化Map
2.3.1 V put(K key, V value)
设置 key 对应的 value
public class Test {
public static void main(String[] args) {
Map<String,Integer> map = new TreeMap<>();
map.put("world",2);
map.put("hello",2);
System.out.println(map);
}
}
可以看到结果是按照字母排过序的.
我们看一下源码:
compare:
可以看到比较方式有两种
在我们添加一个没有重写cmopareTo方法的对象后
类型转换异常,当TreeMap 创建时如果有传入 Comparator ,优先按照 Comparator 的规则来排序,如果没有传入 Comparator ,就按照key的 compareTo 方法来排序。如果没传,它会认为你实现了Comparable接口,将你向上强制转换为Comparable类,所以Student类由于没有实现Comparable接口就会转换错误
String类型是有比较器的,所以直接就比较,不会检查是否实现了compareTo方法
实现了Comparable接口,重写compareTo方法后
因此,使用TreeMap时其key必须实现Comparable接口或采用自定义的比较器,否则会抛出java.lang.ClassCastExption异常
两种方式区别不大,一个是key实现Comparable接口,重写compareTo()方法,另一个是在TreeMap的构造函数中创建new Comparator匿名内部类,重写compare 方法
2.3.2 V get(Object key)
返回 key 对应的 value
get方法返回值类型是V, 用int 型变量接收
打印后
2.3.3 V getOrDefault(Object key, V defaultValue)
返回 key 对应的 value,key 不存在,返回默认值
当获取一个不存在的key时,会出现空指针异常
是因为返回null后,int接收不了,可以用Integer接收
使用getOrDefault()方法
key 不存在,返回默认值
2.3.4 Set<K> keySet() Collection<V> values()
返回所有 key 的不重复集合
返回所有 value 的可重复集合
Set<String> set = map.keySet();
System.out.println(set);
Collection<Integer> collection = map.values();
System.out.println(collection);
2.3.5 Set<Map.Entry<K,V>> entrySet()
返回所有的 key-value 映射关系
Map.Entry<K,V>作为Set<>的类型
看一下Entry
Map.Entry<K,V>上文中介绍过,用来存放<key,value>键值对映射关系的内部类
Set中的每一个元素都是Entry类型的
Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
for (Map.Entry<String,Integer> entry : entrySet) {
System.out.println("key:"+entry.getKey()+" "+"value:"+entry.getValue());
}
遍历得到
因此该方法能获取到集合中的key,value,该方法提供了一种遍历map的方式,foreach不能遍历map
foreach遍历必须要实现Iterable接口,但是map没有实现这个接口,因此提供该方法能更好的遍历map,取到key和value
注意:
1.Map是一个接口,不能直接实例化,实例化其实现类(TreeMap或HashMap)
2.Map中存放键值对的key是唯一的,value是可重复的
3.Map中的key可以全部分离出来存到Set中来进行访问(key不能重复)
4.Map中的value可以全部分离出来,放到collection的任何一个子集合中(value可能重复)
5.Map中的值不能直接修改,value可以直接改,有setValue()方法,要修改key,那只能先删除,然后重新插入
3. Set的说明
Set与Map主要的不同有两点:
Set是继承自Collection的接口类
Set中只存储了Key
方法
方法 | 说明 |
---|---|
boolean add(E e) | 添加元素,重复的元素不会被添加成功 |
void clear() | 清空集合 |
boolean contains(Object o) | 判断o是否在集合中 |
Iterator<E> 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中,可以达到去重的效果 |
注意
1.Set是一个接口类,继承自Collection
2.Set中只存储了key,并且key一定要唯一
Set<String> set1 = new TreeSet<>();
set1.add("hello3");
set1.add("hello3");
System.out.println(set1);
这时还是只打印一个,重复的key存不进去
3.Set底层是Map实现的,其使用key与Object的一个默认对象作为键值对插入到Map中的
TreeSet<String> set1 = new TreeSet<>();
set1.add("hello3");
PRESENT就是这里的Object的默认对象,因此在TreeSet中存储值,实际上是存在了TreeMap中,只是value是一个默认值
因为底层是Map实现的,所以,使用Map和Set的时候,传入的Key必须是可比较的,否则就会出现类型转换异常
4. Set最大的功能就是对集合中的元素进行去重
我们生成十个随机数,然后对它进行去重并输出
public static void main(String[] args) {
int[] arr = new int[10];
Random r = new Random();
for (int i = 0; i < 10; i++) {
arr[i] = r.nextInt(5);
}
System.out.println(Arrays.toString(arr));
fun(arr);
}
public static void fun(int[] array){
TreeSet<Integer> treeSet = new TreeSet<>();
for (int i = 0; i < array.length; i++) {
treeSet.add(array[i]);
}
System.out.println(treeSet);
}
5. 实现Set接口的常用类有TreeSet和HashSet,还有一个LinkedHashSet,LinkedHashSet是在HashSet的基础 上维护了一个双向链表来记录元素的插入次序
6. Set中的Key不能修改,如果要修改,先将原来的删除掉,然后再重新插入
7.Set不能插入null的key,TreeMap也不能插入null的key
TreeSet不能有key为null的元素,会报NullPointerException
public void testTreeSet(){
TreeSet<String> set = new TreeSet<>();
set.add(null); //Error NullPointException
}
TreeMap的put方法会调用compareTo方法,对象为null时,会报空指针错
public void testTreeMap(){
TreeMap<String,String> map = new TreeMap<>();
map.put(null,null);
Assert.assertEquals(1,map.size()); //Error NullPointException
}