java--键值对集合(Map)
⽂章⽬录
Map接⼝概述
将键映射到值的对象
不能包含重复的键
每个键最多只能映射到⼀个值
Map接⼝和Collection接⼝的不同
Map是双列的,Collection是单列的
Map的键唯⼀,Collection的⼦体系Set是唯⼀的(实际上Set就是Map的键)
Map集合的数据结构值针对键有效,跟值⽆关,Collection集合的数据结构是针对元素有效
Map接⼝的⽅法列表
注:部分⽅法的作⽤解释可能存在偏差
⽅法作⽤
int size();返回map中 键值对 的个数
boolean isEmpty();判断map是否为空(长度为0)
boolean containsKey(Object key);判断map中是否包含给定键
boolean containsValue(Object value);判断map中是否包含给定值
V get(Object key);根据给定键,获取对应值
V put(K key, V value);,若key不存在,则添加⼀对键值对,返回null;若key已存在则替换其value,返回旧的value V remove(Object key);根据键移除对应键值对
void putAll(Map<? extends K, ? extends V>
m);
添加或设置给定Map所包含的所有键值对
void clear();移除所有键值对
Set keySet();获取以所有键为元素的Set集合
Collection values()获取以所有值为元素的Collection集合Set<Map.Entry<K, V>> entrySet();获取map中所有键值对对象的set集合default V getOrDefault(Object key, V
defaultValue)
返回给定key对应的值,若给定key不存在或值为null则返回给定值defaultValue(1.8新增)
default void forEach(BiConsumer<? super
K, ? super V> action)
遍历map,将每个键值对按照给定消费型函数规则改变(1.8新增)default void replaceAll(BiFunction<? super
K, ? super V, ? extends V> function)遍历map中每个键值对对象,根据给定函数型函数规则替换键值对对象的 值 (1.8新增)
default V putIfAbsent(K key, V value)如果map中不存在给定的key,或给定的key对应的值为null,则添加,否则返回原本的value(1.8新
增)
default boolean remove(Object key, Object
value)
若map中已存在给定的key-value键值对则移除,返回true;否则返回false(1.8新增)
value)
若map中已存在给定的key-value键值对则移除,返回true;否则返回false(1.8新增)
default boolean replace(K key, V oldValue, V
newValue)若map中已存在给定的key-oldValue键值对,则替换为给定的key-newValue。返回true;否则返回
false(1.8新增)
default V replace(K key, V value)若map中已存在给定key且其映射的值不为null,则将其值替换为给定value,返回原本值,否则返回
null
default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)若给定key不存在或其所对应的值为null,则按照给定函数式函数计算得出新value作为该key的对应值,返回该新value;若给定key对应的值不为null或计算得出的新value为null,则返回原本的value(1.8新
增)
default V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
若给定key存在且其对应值不为null,则按照给定函数式函数计算得出newValue,若newValue不为空,则将给定key的旧值替换为newValue,返回newValue,若newValue为空则移除给定key,返回
null;否则返回null。(1.8新增)
default V compute(K key,BiFunction<?
super K, ? super V, ? extends V>
remappingFunction)根据给定函数式函数得出newValue。若newValue不为null,则添加或替换key-newValue键值对,返回newValue;若newValue为空,则移除key,返回null
default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)
如果Map中key对应的映射不存在或者为null,则将value关联到key上;否则执⾏remappingFunction,如果执⾏结果为null则删除key的映射,否则⽤该结果跟key关联。
⽅法作⽤
部分⽅法测试
注:打印结果以注释⽅式呈现,部分例⼦可不能不是很恰当,见笑
@Test
public void test1(){
Map<Integer, String> map = new HashMap<>();
//put⽅法
map.put(1, "1");
map.put(2, "2");
String put = map.put(3, "3");
String put1 = map.put(3, "33");
System.out.println(put); // null
System.out.println(put1); // 3
System.out.println(map); //{1=1, 2=2, 3=33}
Map<Integer, String> map2 = new HashMap<>();
map2.put(1, "11");
map2.put(2, "22");
map2.put(4, "44");
//putAll⽅法
map.putAll(map2);
System.out.println(map); //{1=11, 2=22, 3=33, 4=44}
//keySet()
Set<Integer> keySet = map.keySet();
System.out.println(keySet);// [1, 2, 3, 4]
//values()
Collection<String> values = map.values();
System.out.println(values); //[11, 22, 33, 44]
//entrySet()
Set<Map.Entry<Integer, String>> entries = Set();
//Map遍历的⼀种⽅式(注意此处调⽤的是Iterable的forEach⽅法)
entries.forEach(e ->{
Integer key = e.getKey();
String value = e.getValue();
System.out.println(key + "--" + value);
});
/* 结果:
1--11
replaceall()2--22
3--33
4--44
*/
//getOrDefault⽅法
String aDefault = OrDefault(5, "不存在该key");
System.out.println(aDefault);// 不存在该key
//forEach⽅法
map.forEach((key, value) ->{
if ((key & 1) == 1){
value += "(key是奇数)";
}else{
value += "(key是偶数)";
}
map.put(key, value);
});
System.out.println(map); //{1=11(key是奇数), 2=22(key是偶数), 3=33(key是奇数), 4=44(key是偶数)}
//replaceAll⽅法
if (dsWith(")")){
return val.substring(0, 2);
}
String() + key + toString();
});
System.out.println(map); //{1=11, 2=22, 3=33, 4=44}
//putIfAbsent⽅法
String putIfAbsent1 = map.putIfAbsent(4, "王富贵");// 已存在该key -> 4==44
System.out.println(putIfAbsent1); // 44
System.out.println(map); //{1=11, 2=22, 3=33, 4=44}
String putIfAbsent2 = map.putIfAbsent(5, "55");// 不存在该key
System.out.println(putIfAbsent2); // null
System.out.println(map); //{1=11, 2=22, 3=33, 4=44, 5=55}
//remove(key,val)⽅法
System.out.println("移除键值对 5==55 :" + ve(5, "55")); //移除键值对 5==55 :true
System.out.println(map); //{1=11, 2=22, 3=33, 4=44}
System.out.println("移除键值对 4==520 : " + ve(4, "520")); //移除键值对 4==520 : false
System.out.println(map); //{1=11, 2=22, 3=33, 4=44}
//replace(key,oldVal,newOld)⽅法
boolean replace = place(4, "44", "newOld 44");
System.out.println(replace); //true
System.out.println(map); //{1=11, 2=22, 3=33, 4=newOld 44}
//replace(key,val)⽅法
String oldVal = place(4, "44");
System.out.println(oldVal); //newOld 44
System.out.println(map); //{1=11, 2=22, 3=33, 4=44}
//computeIfAbsent⽅法
String s = mapputeIfAbsent(4, key -> String() + String());//给定key存在且对应值不为空 System.out.println(s); //44
System.out.println(map); //{1=11, 2=22, 3=33, 4=44}
String s2 = mapputeIfAbsent(5, key -> String() + String());//给定key不存在
System.out.println(s2); //55
System.out.println(map); //{1=11, 2=22, 3=33, 4=44, 5=55}
//computeIfPresent⽅法
String present1 = mapputeIfPresent(5, (key, oldValue) ->{
String val = String() + String(); // 55
if (oldValue.equals(val)){
return val + ":符合条件";
}
return null;
});
});
System.out.println(present1); //55:符合条件
System.out.println(map); //{1=11, 2=22, 3=33, 4=44, 5=55:符合条件}
//再次执⾏ 5=55:符合条件
String present2 = mapputeIfPresent(5, (key, oldValue) ->{
String val = String() + String(); // 55
if (oldValue.equals(val)){
return val + ":符合条件";
}
return null; //newValue为null时将删除该键值对
});
System.out.println(present2); //null
System.out.println(map); //{1=11, 2=22, 3=33, 4=44}
//compute⽅法
String compute = mappute(5, (k, v) -> k.toString() + k.toString());
System.out.println(compute); //55
System.out.println(map); //{1=11, 2=22, 3=33, 4=44, 5=55}
//merge⽅法
String merge = (6, "新val", (oldValue, newValue) -> oldValue + newValue);//给定key不存在
System.out.println(merge); //新val
System.out.println(map); //{1=11, 2=22, 3=33, 4=44, 5=55, 6=新val}
String merge2 = (6, "66", (oldValue, newValue) -> newValue);//给定key已存在
System.out.println(merge2); //66
System.out.println(map); //{1=11, 2=22, 3=33, 4=44, 5=55, 6=66}
}
Map接⼝的实现类
HashMap
键是哈希表结构,可以保证键的唯⼀性。线程不安全,HashMap最多只允许⼀条记录的键为Null,允许多条记录的值为 Null;。
jdk1.8前后HashMap底层结构的变化(原⽂:):
⼀、在JDK1.8之前,HashMap的底层是采⽤数组+链表的⽅法,即⽤链表处理哈希冲突。插⼊元素是先通过HashMap中Key的hashcode()⽅法计算出插⼊到数组的位置,如果数组当前位置没有元素,
直接插⼊;如果当前位置已有元素,通过equals⽅法⽐较key,如果key也相同,直接覆盖,如果key不相同,插⼊链表中。(即拉链法:数组每⼀格都代表可以“下挂”⼀个链表,当遇到哈希冲突时,插⼊到链表中即可。)
⼆、Jdk1.8之后,HashMap的底层结构在处理哈希冲突时有了较⼤改变,即采⽤数组+链表+红⿊树的结构,当链表长度⼤于8时,链表⾃动转化为⼆叉树。这样做的好处是,提⾼当链表长度过长时,搜索速度过慢的问题。
有关HashMap的更多理解可参考这篇⽂章:
LinkedHashMap
继承⾃HashMap。使⽤Map接⼝的哈希表和链表实现,具有可预知的迭代顺序。
此实现与HashMap的不同之处在于:LinkedHashMap维护着⼀个双向循环链表。此链表定义了迭代顺序,该迭代顺序通常就是存放元素的顺序。遍历速度⽐HashMap慢。
⼩测试
@Test
public void test2(){
HashMap<String,String> hashMap = new HashMap<>();
hashMap.put("hello","11");
hashMap.put("hash","22");
hashMap.put("map","33");
hashMap.put("Good","44");
hashMap.put("Luck","55");
hashMap.put(null,null);//允许⼀个键为null
Set<Map.Entry<String, String>> entries = Set();
entries.forEach(System.out::println);
/* 结果(遍历顺序与添加顺序不同):
null=null
Luck=33
hello=11
Good=33
map=33
hash=22
*/
System.out.println("-----------------------------");
LinkedHashMap<String,String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("hello","11");
linkedHashMap.put("hash","22");
linkedHashMap.put("map","33");
linkedHashMap.put("Good","44");
linkedHashMap.put("Luck","55");
linkedHashMap.put(null,null);//允许⼀个键为null
Set<Map.Entry<String, String>> entrySet = Set();
entrySet.forEach(System.out::println);
/* 结果(遍历顺序与添加顺序相同):
hello=11
hash=22
map=33
Good=44
Luck=55
null=null
*/
}
TreeMap
键是红⿊树结构,可以保证键的排序(⾃然排序或⾃定义排序)和唯⼀性。线程不安全。不允许有null键,但允许有null值。⼩测试
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论