文章目录
1. HashMap和HashSet的基本使用和作用
1.1 基本使用
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
Map<Integer, Integer> map = new HashMap<>();
Set<Integer> set = new HashSet<>();
1.2 作用
1.2.1 HashMap
- HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
- HashMap 实现了 Map 接口,
根据键的 HashCode 值存储数据,具有很快的访问速度
,最多允许一条记录的键为 null,不支持线程同步。 - HashMap 是无序的,即不会记录插入的顺序。
- HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。
注意:HashMap就是快速查找,不用去遍历根据word值判断HashMap中是否存在相等的key值,再去寻找对应的value值。直接使用
map.getOrDefault(word, 0);
如果存在与word值相等的key值,直接返回对应的value值,否则返回0。
1.2.2 HashSet
- HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。
- HashSet 允许有 null 值。
- HashSet 是无序的,即不会记录插入的顺序。
- HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须在多线程访问时显式同步对 HashSet 的并发访问。
- HashSet 实现了 Set 接口。
2. HashMap和HashSet的嵌套使用
分析:我们知道java的数据类型分为基本数据类型和引用数据类型,而引用数据类型中包含类和接口。String类型属于类这一部分,而HashSet和HashMap也是类,所以,HashMap和HashSet是一种数据类型,在HashMap中嵌套HashSet与基本数据类型没什么区别。不用特殊对待。
Map<Integer, String> map = new HashMap<>();
Map<Integer, Set<Integer>> mapSet = new HashMap<>();
3. 举例
eg1: leetcode–1817. 查找用户活跃分钟数
1817. 查找用户活跃分钟数
我的思路:由于我最开始不知道HashMap和HashSet可以嵌套使用,所以我定义的HashMap<Integer, String>中使用key来存储对应的用户ID,用String的固定模式" " + 分钟时刻的模式来存储用户执行操作的分钟,如果字符串中不包含新来的" " + 分钟时刻,就加入字符串,否则说明已经有了该分钟时刻,就不加入字符串就可以了,但耗时和存储空间用的多。具体实现如下:
class Solution {
public int[] findingUsersActiveMinutes(int[][] logs, int k) {
int[] answer = new int[k];
HashMap<Integer, String> uAM = new HashMap<>();
for (int i = 0; i < logs.length; i++) {
String str = " " + logs[i][1];
if (!uAM.containsKey(logs[i][0]))
uAM.put(logs[i][0], str);
else {
if (!uAM.get(logs[i][0]).contains(str))
uAM.put(logs[i][0], uAM.get(logs[i][0]) + str);
}
}
for (Integer key : uAM.keySet()) {
String str = uAM.get(key);
int times = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == ' ')
times++;
}
answer[times - 1]++;
}
return answer;
}
}
HashMap中嵌套使用HashSet的代码实现如下:
class Solution {
public int[] findingUsersActiveMinutes(int[][] logs, int k) {
int[] answer = new int[k];
Map<Integer, Set<Integer>> map = new HashMap<>();
for(int i = 0; i < logs.length; i++){
Set<Integer> set = new HashSet<>();
if (map.get(logs[i][0]) != null)
set = map.get(logs[i][0]);
set.add(logs[i][1]);
map.put(logs[i][0], set);
}
for (Set<Integer> value : map.values())
answer[value.size() - 1]++;
return answer;
}
}
说明:
- HashMap中的get方法:如果HashMap不存在key键,那么map.get(key)会等于null;
- HashMap中的put方法:如果HashMap中不存在key ⇒ \Rightarrow ⇒ value的映射,那么map.put(key, value)就会建立key ⇒ \Rightarrow ⇒ value的映射;如果HashMap中存在key ⇒ \Rightarrow ⇒ value0的映射,那么map.put(key, value)就会舍弃原来的映射,建立新的key ⇒ \Rightarrow ⇒ value的映射。
- 关于HashMap的循环遍历的方式说明:
- 如果循环体中仅仅值使用到key值,则遍历方式为
Map<Integer, String> map = new HashMap<>();
for (Integer key : map.keySet()) {
//...
}
- 如果循环体中仅仅使用到value值,则遍历方式为
Map<Integer, String> map = new HashMap<>();
for (String value : map.values()) {
//...
}
- 如果循环体中key值和value值都使用,则遍历方式为
Map<Integer, String> map = new HashMap<>();
for (Map.Entry<Integer, String> entry : map.entrySet()) {
//...
entry.getKey();
entry.getValue();
}
4. List的嵌套
由于List属于接口,所以和基本数据类型一样也能被嵌套使用。
import java.util.ArrayList;
import java.util.List;
public class test {
public static void main(String[] args) {
List<List<Integer>> a = new ArrayList<>();
List<Integer> b=new ArrayList<>();
b.add(1);
b.add(2);
b.add(3);
System.out.println(b);
List<Integer> c= new ArrayList<>();
c.add(4);
c.add(5);
c.add(6);
System.out.println(c);
a.add(b);
a.add(c);
System.out.println(a);
}
}