Set和Map

一、关于集合的体系结构

在这里插入图片描述

  • 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>();
		//V put(K key,V value):添加元素
		map.put("张无忌","赵敏");
		map.put("郭靖","黄蓉");
		map.put("杨过","小龙女");
		//V remove(Object key):根据键删除键值对元素
		System.out.println(map.remove("郭靖"));
		System.out.println(map.remove("郭襄"));
		//void clear():移除所有的键值对元素
		// map.clear();
		//boolean containsKey(Object key):判断集合是否包含指定的键
		System.out.println(map.containsKey("郭靖"));
        System.out.println(map.containsKey("郭襄"));
		//boolean isEmpty():判断集合是否为空
        System.out.println(map.isEmpty());
 		//int size():集合的长度,也就是集合中键值对的个数
		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("杨过", "小龙女");
		//V get(Object key):根据键获取值
		// System.out.println(map.get("张无忌"));
		// System.out.println(map.get("张三丰"));
		
		//Set<K> keySet():获取所有键的集合
		// Set<String> keySet = map.keySet();
		// for(String key : keySet) {
			// System.out.println(key);
		// }
		
		//Collection<V> values():获取所有值的集合
		Collection<String> values = map.values();
		for(String value : values) {
			System.out.println(value);
		}
	}
}

2.3Map需要注意的点

  1. Map是一个接口,不能直接实例化对象,如果要实例化对象只能实例化其实现类TreeMap或者HashMap
  2. Map中存放键值对的Key是唯一的,value是可以重复的
  3. 在Map中插入键值对时,key可以为空,value也可以为空
  4. Map中的Key可以全部分离出来,存储到Set中来进行访问(因为Key不能重复)。
  5. Map中的value可以全部分离出来,存储在Collection的任何一个子集合中(value可能有重复)。
  6. Map中键值对的Key不能直接修改,value可以修改,如果要修改key,只能先将该key删除掉,然后再来进行
    重新插入。

2.4HashMap与TreeMap的比较

在这里插入图片描述

三、Set的使用

3.1Set集合概述和特点

  • 不可以存储重复元素
  • 没有索引,不能使用普通for循环遍历

3.2Set常用方法

在这里插入图片描述

3.3Set需要注意的点

  1. Set是继承自Collection的一个接口类
  2. Set中只存储了key,并且要求key一定要唯一
  3. Set的底层是使用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中的
  4. Set最大的功能就是对集合中的元素进行去重
  5. 实现Set接口的常用类有TreeSet和HashSet,还有一个LinkedHashSet,LinkedHashSet是在HashSet的基础上维护了一个双向链表来记录元素的插入次序。
  6. Set中的Key不能修改,如果要修改,先将原来的删除掉,然后再重新插入
  7. Set中能插入null的key

3.4TreeSet和HashSet的比较

在这里插入图片描述

四、相关面试题及编程题

HashMap的相关面试题:List与HashMap相关面试题

  1. 只出现一次的数据
    在这里插入图片描述
  • 与运算来做
class Solution {
    public int singleNumber(int[] nums) {
        int single = 0;
        for (int num : nums) {
            single ^= num;
        }
        return single;
    }
}
  • HashSet来做
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.复制带随机指针的链链表
在这里插入图片描述
在这里插入图片描述

/*
// Definition for a Node.
class Node {
    int val;
    Node next;
    Node random;

    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}
*/

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){//堆顶元素的值小 堆顶出 me进
                    minHeap.poll();
                    minHeap.offer(me);
                }

            }
        }
        //将出现频率为前K个的String放入List
        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;

    }
}
  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值