map的基础理解
话不多说,先上图,可以这样简单的对容器中的map进行分类:
我们在Java开发中,除了最常用的基本数据类型和String对象之外,也会经常用到集合类。集合类中存放的都是对象的引用,而非对象本身,为了语言上的便利,我们暂且把集合中的对象默认为集合中对象的引用。
集合只用于存储对象,集合的长度是可变的,集合中可以存储不同数据类型的对象。集合类可以分为两大类,一类是Collection,另外一类是Map。
讲到这里,有一个小插曲要说一下。
严格意义上讲,map并不是一个集合。 而是两个集合之间的的映射关系,因为它并没有继承Collection接口也没有继承Iterable接口,但是map可以存储数据,每次存储集合A中的一个值和与之对应的集合B中的一个值,所以我们还是习惯上把map称之为集合。所以这也是为什么不能对map进行for-each操作了,但是我们可以对key集合、value集合和entry集合进行迭代操作。
Map集合与Set集合元素的存储形式很像,如Set接口下有HashSet、LinkedHashSet、SortedSet(接口)、TreeSet、EnumSet等实现类和子接口,而Map接口下则有HashMap、LinkedHashMap、SortedMap(接口)、TreeMap、EnumMap等实现类和子接口。
Map有时也称为字典,或关联数组。
Map中包括一个内部类:Entry。该类封装了一个key-value对,Entry包含三个方法:
Object getkey():返回该Entry里包含的key值。
Object getValue():返回该Entry里包含的value值。
Object setValue():设置该Entry里包含的value值,并返回新设置的value值。
可以把Map理解成一个特殊的Set,只是该Set里包含的集合元素是Entry对象,而不是普通对象。
Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种集合的视图:
Set keyset():返回map中所有key的一个set视图
Collection values():返回map中所有value的一个Collection视图
Set<map.entry<k,v>> entrySet():返回map中所有映射的一个集合视图
这里用一些简单的示例对上面的话做一下解释:
public static void main(String[] args) {
//new的是map的子类,并定义key、value的数据类型
HashMap<String, String> map = new HashMap<>();
map.put("北京","安河桥北");
map.put("上海","虹桥机场");
map.put("广州","嘉禾望岗");
map.put("深圳","翻身");
System.out.println(map);
//此时直接打印结果:{上海=虹桥机场, 广州=嘉禾望岗, 北京=安河桥北, 深圳=翻身}
//迭代所有的key组成的集合
Set<String> keySet = map.keySet();
for (String s : keySet) {
System.out.println(s);
}
//迭代所有的value组成的集合
Collection<String> values = map.values();
for (String value : values) {
System.out.println(value);
}
//迭代所有的entry对象
Set<Map.Entry<String, String>> entrySet = map.entrySet();
//entrySet的数据类型是Set,泛型是 Map.Entry<String, String>
for (Map.Entry<String, String> entry : entrySet) {
String key = entry.getKey();// 获取此时 entry 的key
String value = entry.getValue();// 获取此时 entry 的value
System.out.println(key+":"+value);// 把每个键值对打印出来
entry.setValue("?"); // 修改map中的value值,在for循环之外查看更新后的value
}
System.out.println(map.get("北京"));// 打印结果:?
System.out.println(map.get("上海"));// 打印结果:?
System.out.println(map.get("广州"));// 打印结果:?
System.out.println(map.get("深圳"));// 打印结果:?
}
注意: 1.map集合不允许key重复,其value值可以重复。
2.map本身是一个接口,不能通过new一个map实现对象的初始化,常见的形式为:
Map<Key,Value> mapName = new HashMap<Key,Value>();
常见的实现类有:HashMap、LinkedHashMap、HashTabel、TreeMap等
3.map里存储的是引用类型的对象,所以键值对key-value都是引用类型(基本类型的包装类)
4.map中用到的数据结构都是应用在“键”上的
5.根据key获取value,当key不存在时,获取到的value为null
6.put方法,存入已有的key时,会新值覆盖旧值
map常用方法:
- void clear( ) 清空map中所有键值对,没有返回值
- Object remove(Object key) 删除指定key的键值对映射,并返回key对应的value值
- boolean remove(Object Key,Object Value) 删除指定key-value键值对,并返回是否删除成功的 boolean 值
- Object put(Object k, Object v) 将指定键值对存入map,返回null;如果指定key已经存在,则新值覆盖旧值,并返回旧值
- void putAll(Map m) 将指定map中的所有键值对存入新的map中,并去重(新值覆盖旧值)
- int size( ) 返回map中键值对的个数
- boolean isEmpty( ) 判断map是否为空,为空则返回 true,不为空则返回 false
- boolean containsKey(Object key) 判断map中是否存在指定key,并返回一个 boolean 值
- boolean containsValue(Object value) 判断map中是否存在指定value,并返回一个boolean值
- Object get(Object k) 根据指定key获取map中的value值,如果不存在指定key,则返回null
- int hashCode( ) 返回指定键或值的哈希码值
map的四种遍历方法
Map集合不能直接遍历,只能通过某种方式转换为“Set集合”进行遍历。
方法一:先获取所有key,通过key获取value
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
方法二:不获取key,直接获取所有value
for (String value : map.values()) {
System.out.println("value= " + value);
}
方法三:通过entry对象获取key、value
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " value= " + entry.getValue());
}
方法四:通过entry对象获取一个迭代器对象,然后利用迭代器的方法进行遍历
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " value= " + entry.getValue());
}
上面第四种方法提到了 Iterator (迭代器),这里我们简单讲讲迭代器,其中的细节以后再讲
迭代器(Iterator)模式,又叫做游标模式,它提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。
简单的说,迭代器就是一个接口Iterator,实现该接口的类就叫做可迭代类,这些类多数时候指的就是java.util包下的集合类
迭代器就是专门取出集合元素的对象,但是该对象比较特殊,不能直接创建对象(通过new),该对象是以内部类的形式存在于每个集合类的内部。Collection接口中定义了获取集合类迭代器的方法(iterator()),所以所有的Collection体系集合都可以获取自身的迭代器。
示例:
public class RunoobTest {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(12);
numbers.add(8);
numbers.add(2);
numbers.add(23);
Iterator<Integer> it = numbers.iterator();
while(it.hasNext()) {
Integer i = it.next();
if(i < 10) {
it.remove(); // 删除小于 10 的元素
}
}
System.out.println(numbers);
}
}
输出结果:[12, 23]
通过iterator()方法获取一个迭代器对象
hasNext() 该方法用于判断集合中是否还有元素
next() 该方法获取集合中的元素值
remove() 该方法删除当前迭代器的元素值