一、关于集合的体系结构
- Set是继承自Collection的接口类,Set中只存储了Key。
- Map是一个接口类,该类没有继承自Collection,该类中存储的是<K,V>结构的键值对,并且K一定是唯一的,不
能重复。
二、Map的使用
2.1关于Map.Entry的说明
- Map.Entry<K, V> 是Map内部实现的用来存放<key, value>键值对映射关系的内部类,该内部类中主要提供了<key, value>的获取,value的设置以及Key的比较方式。
2.2Map的常用方法说明
-
方法介绍 -
代码演示
public class MapDemo02 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
System.out.println(map.remove("郭靖"));
System.out.println(map.remove("郭襄"));
System.out.println(map.containsKey("郭靖"));
System.out.println(map.containsKey("郭襄"));
System.out.println(map.isEmpty());
System.out.println(map.size());
System.out.println(map);
}
}
public class MapDemo03 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("张无忌", "赵敏");
map.put("郭靖", "黄蓉");
map.put("杨过", "小龙女");
Collection<String> values = map.values();
for(String value : values) {
System.out.println(value);
}
}
}
2.3Map需要注意的点
- Map是一个接口,不能直接实例化对象,如果要实例化对象只能实例化其实现类TreeMap或者HashMap
- Map中存放键值对的Key是唯一的,value是可以重复的
- 在Map中插入键值对时,key可以为空,value也可以为空
- Map中的Key可以全部分离出来,存储到Set中来进行访问(因为Key不能重复)。
- Map中的value可以全部分离出来,存储在Collection的任何一个子集合中(value可能有重复)。
- Map中键值对的Key不能直接修改,value可以修改,如果要修改key,只能先将该key删除掉,然后再来进行
重新插入。
2.4HashMap与TreeMap的比较
三、Set的使用
3.1Set集合概述和特点
- 不可以存储重复元素
- 没有索引,不能使用普通for循环遍历
3.2Set常用方法
3.3Set需要注意的点
- Set是继承自Collection的一个接口类
- Set中只存储了key,并且要求key一定要唯一
- Set的底层是使用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中的
- Set最大的功能就是对集合中的元素进行去重
- 实现Set接口的常用类有TreeSet和HashSet,还有一个LinkedHashSet,LinkedHashSet是在HashSet的基础上维护了一个双向链表来记录元素的插入次序。
- Set中的Key不能修改,如果要修改,先将原来的删除掉,然后再重新插入
- Set中能插入null的key
3.4TreeSet和HashSet的比较
四、相关面试题及编程题
HashMap的相关面试题:List与HashMap相关面试题
- 只出现一次的数据
class Solution {
public int singleNumber(int[] nums) {
int single = 0;
for (int num : nums) {
single ^= num;
}
return single;
}
}
class Solution {
public int singleNumber(int[] nums) {
Set<Integer> set=new HashSet<>();
for(int x:nums){
if(!set.contains(x)){
set.add(x);
}else{
set.remove(x);
}
}
return set.iterator().next();
}
}
2.复制带随机指针的链链表
class Solution {
public Node copyRandomList(Node head) {
if(head==null) return null;
Map<Node,Node> map=new HashMap<>();
Node cur=head;
while(cur!=null){
Node list=new Node(cur.val);
map.put(cur,list);
cur=cur.next;
}
cur=head;
while(cur!=null){
map.get(cur).next=map.get(cur.next);
map.get(cur).random=map.get(cur.random);
cur=cur.next;
}
return map.get(head);
}
}
3.宝石与石头
class Solution {
public int numJewelsInStones(String jewels, String stones) {
Set<Character> set=new HashSet<>();
for(int i=0;i<jewels.length();i++){
set.add(jewels.charAt(i));
}
int res=0;
for(int i=0;i<stones.length();i++){
if(set.contains(stones.charAt(i))){
res++;
}
}
return res;
}
}
4.坏键盘打字
- 解题思路
1.将打印的字符串,转化为大写放入Set中 2.(遍历输入的字符串,如果set中不包含就打印,但是会打印重复的键,所以:) 3.因为打印坏的键不能重复,所以在定义个Set 名为setBroken 打印前如果set和setBroken中都不含该字符在打印,打印完再将打印的字符加入setBroken中
import java.util.*;
public class Main{
public static void fun3(String str1,String str2){
Set <Character> set=new HashSet<>();
for(char ch:str2.toUpperCase().toCharArray()){
set.add(ch);
}
Set <Character> setBroken=new HashSet<>();
for(char ch:str1.toUpperCase().toCharArray()){
if(!set.contains(ch)&&!setBroken.contains(ch)){
System.out.print(ch);
setBroken.add(ch);
}
}
}
public static void main(String [] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNextLine()){
String str1=sc.nextLine();
String str2=sc.nextLine();
fun3(str1,str2);
}
}
}
5.前K个高频单词
- 解题思路
1.将world里的字符串放入map中,Map<String,Integer>,并统计String出现的次数 2.找频率最大的字符,所以用小堆PriorityQueue<Map.Entry<String,Integer>> 3.跟topK问题一样解 4.遍历Map中的所有Entry,如果新的Emtry的value值大于堆顶的Value(新Entry的频率大),则堆顶元素出堆,新的Entry入 5.如果频率相等考虑String(key)的元素大小,若字母小 堆先出 后入堆 6.因为PriorityQueue是小堆所以 实现Comparator重写compare时是o1.getValue()-o2.getValue();最后当堆不满K个元素出现Value相同时,要进行调整 当(key大的话交换)
class Solution {
public List<String> topKFrequent(String[] words, int k) {
Map<String,Integer> map=new HashMap<>();
for(String s: words){
if(map.get(s)==null){
map.put(s,1);
}else{
Integer value=map.get(s);
map.put(s,value+1);
}
}
PriorityQueue<Map.Entry<String,Integer>> minHeap=new PriorityQueue<>(k,
new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
if(o1.getValue().compareTo(o2.getValue())==0){
return o2.getKey().compareTo(o1.getKey());
}
return o1.getValue()-o2.getValue();
}
});
for(Map.Entry<String,Integer>me: map.entrySet() ){
if(minHeap.size()<k){
minHeap.offer(me);
}else{
Map.Entry<String,Integer> top=minHeap.peek();
if(top.getValue().compareTo(me.getValue())==0){
if(top.getKey().compareTo(me.getKey())>0){
minHeap.poll();
minHeap.offer(me);
}
}else if(top.getValue().compareTo(me.getValue())<0){
minHeap.poll();
minHeap.offer(me);
}
}
}
List<String> ret=new ArrayList<>();
for(int i=0;i<k;i++){
Map.Entry<String,Integer> top=minHeap.poll();
ret.add(top.getKey());
}
Collections.reverse(ret);
return ret;
}
}
|