Java集合-Map

Mapjava.util.Map)接口,代表着keyvalue间的映射,更具体地说,Java映射可以存储键和值对,一旦存储在地图中,以后就可以只使用键来查找值。Map接口不是Collection 的子接口,因此,它的行为与其他Collection 类型稍有不同。

Map的实现

既然Map是个接口,因此初始化时需要使用她的具体实现,Map包括以下实现类:

  • java.util.HashMap
  • java.util.Hashtable
  • java.util.EnumMap
  • java.util.IdentityHashMap
  • java.util.LinkedHashMap
  • java.util.Properties
  • java.util.TreeMap
  • java.util.WeakHashMap

根据我的经验来最常用的是HashMapTreeMap在迭代映射时,每一个Map实现的行为都与元素的顺序以及在映射中插入和访问元素所需的时间(big O表示法)稍有不同。

HashMap映射键值,但是不保证存储在map的内部顺序。

TreeMap 同样映射键值,但是可以保证key或者value的顺序。

如不需要元素的顺序的话可以使用HashMap,因为HashMap速度很快,否则的话使用TreeMap

创建Map

创建新的Map必须使用它的实现之一:

Map mapA = new HashMap();

Map mapB = new TreeMap();

 

Map的泛型

默认可以往Map里面添加任何对象,但是用了泛型后,可以限制其类型:

Map<String, MyObject> map =
    new HashMap<String, MyObject>();

 

这个Mao只能接受String类型的KeyMyObject 实例的value,同时访问和迭代它们不需要强制类型转换:

for(MyObject anObject : map.values()){
   //do someting with anObject...
}

for(String key : map.keySet()){
   MyObject value = map.get(key);
   //do something to value
}

 

如果指定要往Map中插入的对象,则定义时考虑使用泛型,这样避免了往Map中添加错误的对象。

Map中插入元素

可以通过put()方法添加元素: 

Map<String, String> map = new HashMap<>();

map.put("key1", "element 1");
map.put("key2", "element 2");
map.put("key3", "element 3");

 

调用了三次put()方法添加键值,可以通过键key获取对应的值value。

只能插入对象

Map的键值只能插入对象,如果将原始值(例如intdouble等)作为键或值传递给映射,则在作为参数传递之前,原始值将自动装箱,下面是自动装箱的例子:

 
map.put("key", 123);

上面的例子中,value的值添加了原始值intjava对自动装箱变成Integer实例,因为put()方法需要的是对象实例。

后续插入相同的键key

一个keyMap中只能出现一次,这意味着Map只能存在同一对键值对,也就是同一个Map中只能存在一个“key1“的key值。如果多次调用put()方法插入相同的值,那么之前的值会被覆盖。

Null值的Key

可以用null作为key放到Map中:

Map map = new HashMap();

map.put(null, "value for null key");

 

可以通过get()方法获取key为null的值: 

Map<String, String> map = new HashMap<>();

String value = map.get(null);

 

Null值得Values

Value得值同样允许为null

 
map.put("D", null);

请记住,稍后使用该键调用get()时将得到一个null-因此这将返回null

 
Object value = map.get("D");

代码执行后value变量的值将是null。 

把另外一个Map中的所有元素插入Map

Map接口中有一个putAll()方法,可以将另外一个Map实例中的所有键值拷贝到当前Map中,实际上就是两个Map的合集,下面是代码:

Map<String, String> mapA = new HashMap<>();
mapA.put("key1", "value1");
mapA.put("key2", "value2");

Map<String, String> mapB = new HashMap<>();
mapB.putAll(mapA);

 

执行完代码后,mapB 将包含mapA中所有的键值对,条目的复制只有一种方式。调用 mapB.putAll(mapA) 只会将mapA中的元素添加到mapB中,而不会将mapB中的元素添加到mapA中。

Map中获取元素

可以通过Mapget()方法获取指定key值的元素值:

Map map = new HashMap();

map.put("key1", "value 1");

String element1 = (String) map.get("key1");

 

注意get()方法返回的是 Object,所以需要强制转换成String (因为知道是String)。下面是使用泛型的用法:

Map<String, String> map = new HashMap<>();

map.put("key1", "value 1");

String element1 = map.get("key1");

 

获取默认值

Map接口有个 getOrDefault()方法,这个方法如果Map中没有对应key的值则返回一个默认值:

Map<String, String> map = new HashMap<>();

map.put("A", "1");
map.put("B", "2");
map.put("C", "3");

String value = map.getOrDefault("E", "default value");

 

这个例子Map创建,并且存储了key值为 A B  C。然后调用了MapgetOrDefault()方法,参数为String类型的 Ekey值,因此会返回默认值,因为Map中不包含E这个key, 默认值是作为第二个参数传入的。

检查Map是否包含某个Key

可以使用Map containsKey()方法,检查是否包含某个key:

boolean hasKey = map.containsKey("123");

代码执行后,hasKey变量的值是true,我们map中包含key”123”,否则返回false。

检查是否包含某个Value

Map接口中同样有个containsValue() 方法可以检查是否包含某个value

boolean hasValue = map.containsValue("value 1");

执行完代码后,如果map中有value为“value 1“的值则hasValue返回true,否则返回false。

根据Keys迭代Map

有下面几种方法可以迭代Mapkey

  • 通过key 的Iterator
  • 通过for-each循环
  • 通过Stream

通过KeyIterator

通过Map  keySet()迭代所有的key:

Iterator iterator = map.keySet().iterator();

while(iterator.hasNext(){
  Object key   = iterator.next();
  Object value = map.get(key);
}

 

上面例子,key Iterator返回Map中的每个key,可以调用next()方法,一个个的返回。获取到了key就可以通过get()方法获取到对应的值。下面看看使用泛型:

Map<String, String> map = new HashMap<>();

Iterator<String> iterator = map.keySet().iterator();

while(iterator.hasNext(){
  String key   = iterator.next();
  String value = map.get(key);
}

 

注意泛型同样使用了map.keySet().iterator()方法。

通过Key For-Each循环

Java 5以后可以使用for-each循环迭代 key

for(Object key : map.keySet()) {
    Object value = map.get(key);
}

 

上面代码的效果与前一节中显示的代码非常相似,如果使用了泛型,可以在for-each循环内使用类型,不需要强制转换:

Map<String, String> map = new HashMap<>();

for(String key : map.keySet()) {
    String value = map.get(key);
}

 

通过KeyStream

Java 8以后可以使用Java Stream迭代Map的keys Stream 接口是 Java Stream API 已不是,首先需要从keySey中获取Stream

Map<String, String> map = new HashMap<>();

map.put("one", "first");
map.put("two", "second");
map.put("three", "third");

Stream<String> stream = map.keySet().stream();
stream.forEach((value) -> {
    System.out.println(value);
});    

 

迭代MapValues

同样可以迭代MapValues,首先通过values()获取 Collection,然后迭代Collection,有下面几种方法

  • 通过Iterator
  • 通过for-each 循环
  • 通过Stream

通过ValueIterator

首先获取valuesSetIterator 实例:

Map<String, String> map = new HashMap<>();

Iterator<String> iterator = map.values().iterator();

while(iterator.hasNext()) {
    String nextValue  iterator.next();
}

 

由于一个集合是无序的,所以不能保证值集中的值的迭代顺序,但是如果是TreeSet则可以控制顺序。

使用Value For-Each循环

第二种方法是通过for-each循环:

Map<String, String> map = new HashMap<>();

for(String value : map.values()){
    System.out.println(value);
}

 

通过Value Stream

第三种方法是使用Java Stream API,首先通过Map获取valueSet,然后再获取 Stream

Map<String, String> map = new HashMap<>();

map.put("one", "first");
map.put("two", "second");
map.put("three", "third");

Stream<String> stream = map.values().stream();
stream.forEach((value) -> {
    System.out.println(value);
});
 

迭代MapEntries

同样可以迭代Map中的所有entries,通过entries意味着键值对key + value ,一个entry 同时包含了key value ,之前我们只是迭代了单个key或者value,现在我们同时迭代keyvalue,有下面两种方式:

  • 通过Entry 的Iterator
  • 通过for-each循环

通过Entry Iterator

第一种方式是通过从Map中的entrySet中获取entry Iterator 

Set<Map.Entry<String, String>> entries = map.entrySet();

Iterator<Map.Entry<String, String>> iterator =
    entries.iterator();

while(iterator.hasNext()) {
    Map.Entry<String, String> entry = iterator.next();
    String key   = entry.getKey();
    String value = entry.getValue();
}

 

注意这么从Map.Entry 中获取key value

通过Entry For-Each循环

第二种方法就是使用for-each循环:

for(Map.Entry<String, String> entry : map.entrySet()){
    String key = entry.getKey();
    String value = entry.getValue();
}

 

Map中移除Entries

可以使用(Object key)方法移除Entries,因此,可以移除与键匹配的(keyvalue)对:

 
map.remove("key1");

执行完代码后,map中不再包含key1的键值对。

移除所有Entries

可以通过Mapclear()方法移除所有元素: 

 
map.clear();

替换Map中的Entry

可以通过Map  replace()方法替换其中的元素,如果Map中不存在此key的值,则不会做任何事,则有key存在才会替换,和put()方法的工作原理不一样:

Map map = new HashMap<>();

map.replace("key", "val2"); //no "key" entry, no replace

map.put("key", "val1");     //now contains "key" entry

map.replace("key", "val2"); //now "key" entry replaced

 

执行完代码后key对应的值是val2

获取MapEntries的大小

可以通过 Map size() 方法获取Map entries数量:

 
int entryCount = map.size();

检查Map是否是空

Map接口中有一个专门的方法isEmpty() 检查Map是否是空,如果是空返回true否则返回false

参考:http://tutorials.jenkov.com/java-collections/map.html

http://tutorials.jenkov.com/java-functional-programming/streams.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值