如何在Map中存放重复key
1.概述
本文介绍几种处理Map中一个key对多个value的方法。在JDK标准Map实现中当我们尝试在一个key下插入多个value,那么后续的value会覆盖前面的value。
1
2
3
4
|
Map<String, String> map = new HashMap<>(); assertThat(map.put( "key1" , "value1" )).isEqualTo( null ); assertThat(map.put( "key1" , "value2" )).isEqualTo( "value1" ); assertThat(map.get( "key1" )).isEqualTo( "value2" ); |
2.将集合作为Value
当要处理一个key对多个value的情况,可以将所有value存放在一个集合中。
1
2
3
4
5
6
7
8
|
Map<String, List<String>> map = new HashMap<>(); List<String> list = new ArrayList<>(); map.put( "key1" , list); map.get( "key1" ).add( "value1" ); map.get( "key1" ).add( "value2" ); assertThat(map.get( "key1" ).get( 0 )).isEqualTo( "value1" ); assertThat(map.get( "key1" ).get( 1 )).isEqualTo( "value2" ); |
这种方式处理有多种缺点并且容易产生错误。我们需要为每个key创建一个集合,同时检查集合是否存在并添加或删除值,在Java 8中可以利用compute()方法来简化代码。
1
2
3
4
5
6
|
Map<String, List<String>> map = new HashMap<>(); map.computeIfAbsent( "key1" , k -> new ArrayList<>()).add( "value1" ); map.computeIfAbsent( "key1" , k -> new ArrayList<>()).add( "value2" ); assertThat(map.get( "key1" ).get( 0 )).isEqualTo( "value1" ); assertThat(map.get( "key1" ).get( 1 )).isEqualTo( "value2" ); |
3.使用Apache Commons Collections
添加依赖
1
2
3
4
5
|
< dependency > < groupId >org.apache.commons</ groupId > < artifactId >commons-collections4</ artifactId > < version >4.1</ version > </ dependency > |
3.1 MutiMap
org.apache.commons.collections4.MultiMap接口定义了一个Map,每个key对应一个集合。
1
2
3
4
5
|
MultiMap<String, String> map = new MultiValueMap<>(); map.put( "key1" , "value1" ); map.put( "key1" , "value2" ); assertThat((Collection<String>) map.get( "key1" )) .contains( "value1" , "value2" ); |
这个类非线程安全,4.1版本中已经废弃。
3.2 MultiValuedMap
org.apache.commons.collections4.MultiValuedMap这个接口有多种实现,如ArrayListValuedHashMap与HashSetValuedHashMap。
使用方式如下:
1
2
3
4
5
6
7
8
9
10
11
|
MultiValuedMap<String, String> map = new ArrayListValuedHashMap<>(); map.put( "key1" , "value1" ); map.put( "key1" , "value2" ); map.put( "key1" , "value2" ); assertThat((Collection<String>) map.get( "key1" )) .containsExactly( "value1" , "value2" , "value2" ); MultiValuedMap<String, String> map = new HashSetValuedHashMap<>(); map.put( "key1" , "value1" ); map.put( "key1" , "value1" ); assertThat((Collection<String>) map.get( "key1" )) .containsExactly( "value1" ); |
若不希望value重复那么可以使用HashSetValuedHashMap
1
2
3
4
5
|
MultiValuedMap<String, String> map = new HashSetValuedHashMap<>(); map.put( "key1" , "value1" ); map.put( "key1" , "value1" ); assertThat((Collection<String>) map.get( "key1" )) .containsExactly( "value1" ); |
但ArrayListValuedHashMap,HashSetValuedHashMap及HashSetValuedHashMap都不是线程安全的。为了线程安全可以使用UnmodifiableMultiValuedMap。
1
2
3
4
5
6
7
8
9
|
@Test (expected = UnsupportedOperationException. class ) public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() { MultiValuedMap<String, String> map = new ArrayListValuedHashMap<>(); map.put( "key1" , "value1" ); map.put( "key1" , "value2" ); MultiValuedMap<String, String> immutableMap = MultiMapUtils.unmodifiableMultiValuedMap(map); immutableMap.put( "key1" , "value3" ); } |
4.Guava Multimap
1
2
3
4
5
|
< dependency > < groupId >com.google.guava</ groupId > < artifactId >guava</ artifactId > < version >23.0</ version > </ dependency > |
4.1 LinkedHashMultimap
这个类按插入顺序存放插入元素
1
2
3
4
5
6
|
Multimap<String, String> map = LinkedHashMultimap.create(); map.put( "key1" , "value3" ); map.put( "key1" , "value1" ); map.put( "key1" , "value2" ); assertThat((Collection<String>) map.get( "key1" )) .containsExactly( "value3" , "value1" , "value2" ); |
4.2 TreeMultimap
这个类按可以按自然序访问插入的元素
1
2
3
4
5
6
|
Multimap<String, String> map = TreeMultimap.create(); map.put( "key1" , "value3" ); map.put( "key1" , "value1" ); map.put( "key1" , "value2" ); assertThat((Collection<String>) map.get( "key1" )) .containsExactly( "value1" , "value2" , "value3" ); |
5.自定义MultiMap
如果使用Guava,那么还可以使用Multimap.newMultimap()来定制我们的Map。
小结:一对多思路就是通过集合来存储元素,guava和apache collection为我们提供了现成的工具,如果想自定义还可以使用guava提供的扩展方法来实现。
Map出现重复Key值叠加到上一个key中
Map出现重复Key值将下一个key值叠加在上一个key值中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
List<Map<String, Object>> list = new ArrayList<>(); //模拟数据库数据 for ( int i = 0 ; i < 10 ; i++) { Map<String, Object> map = new HashMap<>(); map.put( "id" , i); map.put( "name" , "张三" + i); if (i < 10 - 1 ) { map.put( "pid" , 2 ); } else { map.put( "pid" , 3 ); } list.add(map); } //运用map中的containsKey方法 Map<String, Object> map1 = new HashMap<>(); for (Map map2 : list) { List<Object> list1 = new ArrayList<>(); String pid = map2.get( "pid" ) + "" ; //如果是重复的那么就进行叠加操作 if (map1.containsKey(pid)) { list1 = (List<Object>) map1.get(pid); } list1.add(map2); map1.put(map2.get( "pid" ) + "" , list1); } System.out.println(map1); } |
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/Revivedsun/article/details/96225010