Map集合是除collection集合外的另一个比较重要的集合,其存储数据的方式为键值对存取。
其特点为:无序,不重复,无索引。
欸,这个特点是不是有点熟悉?对,没错,和我们之前学的Set集合的特点完全一致!
那么,接下来我要告诉你一个炸裂的消息:Set集合的底层其实就是只要键不要值的Map集合!
我们以HashSet为例,点进去查看源码,我们可以看到:
/**
* Constructs a new, empty set; the backing {@code HashMap} instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<>();
}
/**
* Constructs a new set containing the elements in the specified
* collection. The {@code HashMap} is created with default load factor
* (0.75) and an initial capacity sufficient to contain the elements in
* the specified collection.
*
* @param c the collection whose elements are to be placed into this set
* @throws NullPointerException if the specified collection is null
*/
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
/**
* Constructs a new, empty set; the backing {@code HashMap} instance has
* the specified initial capacity and the specified load factor.
*
* @param initialCapacity the initial capacity of the hash map
* @param loadFactor the load factor of the hash map
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
我们可以清晰的看到,HashSet的底层就是一个只要键不要值的HashMap。所以,HashMap的底层原理和HashMap相同。详见HashSet笔记。
认识了HashMap的底层原理之后,我们来认识一下三种常见的Map集合
HashMap、LinkedHashMap、TreeMap:
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();//一行经典代码,按照键 无序,不重复,无索引
map.put("手表",100);
map.put("手表",220); //后面的数据会覆盖掉前面的数据
map.put("手机",1145);
map.put("Java",20);
map.put(null,null);
System.out.println(map);
Map<String,Integer> map1 = new LinkedHashMap<>();//有序,不重复,无索引
map1.put("手表",100);
map1.put("手表",220); //后面的数据会覆盖掉前面的数据
map1.put("手机",1145);
map1.put("Java",20);
map1.put(null,null);
System.out.println(map1);
Map<Integer,String> map2 = new TreeMap<>();//可排序,不重复,无索引(默认按照值升序排序)
map2.put(23,"Java");
map2.put(23,"MySQL");
map2.put(19,"Linux");
map2.put(20,"Spring");
System.out.println(map2);
}
了解完三种常见Map集合后,我们再来看看Map集合的常用方法
因为是Map集合的方法,所以他以下的所有子类(HashMap、LinkedHashMap、TreeMap)都可以使用这些方法。
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();//一行经典代码,按照键 无序,不重复,无索引
map.put("手表",100);
map.put("手表",220);//后面的数据会覆盖掉前面的数据
map.put("手机",1145);
map.put("Java",20);
map.put(null,null);
System.out.println(map);
//map = {null=null, 手表=220, Java=20, 手机=1145};
//2.public int size();获取集合大小
System.out.println(map.size());
//3.public void clear();清空集合
//map.clear();
System.out.println(map);
//4.public boolean isEmpty();判断集合是否为空,是返回true,否返回false
System.out.println(map.isEmpty());
//5.public V get(Object key):根据键获取对应值
System.out.println(map.get("Java"));
System.out.println(map.get("张三"));//不存在则返回null
//6.public V remove(Object key):根据键删除整个元素(删除键会返回键的值)
System.out.println(map.remove("Java"));
//7.public boolean containsKey(Object key):判断是否包含某个键,包含返回true,否则返回false
System.out.println(map.containsKey("Java"));
//8.public boolean containsValue(Object value):判断是否包含某个值
System.out.println(map.containsValue(20));
//9.public Set<K> keySet():获取Map集合的全部键放入到一个set集合中
Set<String> keySet = map.keySet();
System.out.println(keySet);
//10.public Collection<V> values();获取Map集合的全部值放入到一个collection集合中
Collection<Integer> values = map.values();
System.out.println(values);
//11.把其他map集合的数据倒入到自己的集合中来
Map<String,Integer> map1 = new HashMap<>();
map1.put("java1",10);
map1.put("java2",20);
Map<String,Integer> map2 = new HashMap<>();
map2.put("java3",10);
map2.put("java2",222);
map1.putAll(map2);
System.out.println(map1);
System.out.println(map2);
}
OK,讲完了常用方法,我们来说一说如何遍历Map集合。
思考:Map集合是无索引的,故不可以用常规的循环遍历,因此我们需要用增强for循环进行遍历。
于是就可以写成这样:
public static void main(String[] args) {
//准备一个map集合
Map<String,Double>map = new HashMap<>();
map.put("张三",162.1);
map.put("李四",169.8);
map.put("王五",165.8);
map.put("赵六",183.6);
System.out.println(map);
//1.获取Map集合的全部键
Set<String> keys = map.keySet();
System.out.println(keys);
//2.遍历全部的键,根据键获取其对应的值
for (String key:keys){
//根据键获取对应的值
double value = map.get(key);
System.out.println(key+"===>"+value);
}
}
其实,除了增强for循环,我们还可以使用Map集合自带的一种方法:entrySet,这种方法可以将Map集合中的键值对方法。
那么我们就可以写成这样:
public static void main(){
Map<String,Double> map = new HashMap<>();
map.put("张三",162.1);
map.put("李四",169.8);
map.put("王五",165.8);
map.put("赵六",183.6);
System.out.println(map);
Set<Map.Entry<String,Double>> entires = map.entrySet();//用一个Set集合来存,因为是键和值两个数据,所以要用Entry的类型来接,同时因为有两个数据,所以泛型中需要定义两个数据类型
for(Map.Entry<String,Double>entry:entries){
String key = entries.getKey();
Double value = entries.getValue();
System.out.println(key+"-->"+value);
}
}
e,好像有点难理解,没事,我们换一种简单的:
public static void main(String[] args) {
Map<String,Double> map = new HashMap<>();
map.put("张三",162.1);
map.put("李四",169.8);
map.put("王五",165.8);
map.put("赵六",183.6);
System.out.println(map);
//用foreach方法遍历
map.forEach(new BiConsumer<String, Double>() {
@Override
public void accept(String k, Double v) {
System.out.println(k+"-->"+v);
}
});
}
欸,看着咋嫩眼熟嘞,点进去看看源码。哦,原来是函数化接口啊,那么直接lambda表达式秒了!
public static void main(String[] args) {
Map<String,Double> map = new HashMap<>();
map.put("张三",162.1);
map.put("李四",169.8);
map.put("王五",165.8);
map.put("赵六",183.6);
System.out.println(map);
//用foreach方法遍历
map.forEach(new BiConsumer<String, Double>() {
@Override
public void accept(String k, Double v) {
System.out.println(k+"-->"+v);
}
});
//用lambda表达书写foreach遍历
map.forEach((k,v)-> System.out.println(k+"-->"+v));
}