重构Map地图的Java Map [英] Refactoring Java Map of Map of Map
问题描述
我正在审查一个项目的旧代码,并使用 Map
Map
获得数据结构。 地图
(3层地图):
I'm reviewing an old code of an project and got a datastructure as bellow using Map
of Map
of Map
(3-Layered Map):
// data structure
Map<String, Map<String, Map<String, List<String>>>> tagTree
= new HashMap<String, Map<String,Map<String,List<String>>>>();
并从Map中获取值(我认为这是不错的部分)
And fetch the values from Map (I think this is the nice part)
// fetch at tag values
List<String> tagList1 = tagTree.get("Java").get("Active").get("Tags");
List<String> tagList2 = tagTree.get("Java").get("Latest").get("SubTags");
将值放在Map中(有点复杂且容易出错)
Put the values in Map (little bit complex and error-prone)
// put values
Map<String, Map<String, List<String>>> javaLangMap = new HashMap<String, Map<String, List<String>>>();
Map<String, List<String>> javaStatusMap = new HashMap<String, List<String>>();
List<String> javaTagList = new ArrayList<String>();
javaTagList.add("Java-OOP");
javaTagList.add("Java-Variables");
// put tag list
javaStatusMap.put("Tags", javaTagList);
// put status-wise tag
javaLangMap.put("Active", javaStatusMap);
// put language-wise tag
tagTree.put("Java", javaLangMap);
目前这是用于维持以下结构
Currently this is serving to maintain following structure
TagLanguage - > TagStatus - > TagType - > TagList
TagLanguage -> TagStatus -> TagType -> TagList
我打算重构这个地图,因为对于其他开发者来说很难阅读。
I'm planning to refactor this Map because it's hard to read for other developers.
请分享您的想法如何通过考虑以下情况来做到这一点:
Please share your Idea How to do it by considering following cases:
- 在运行时可以更改所有四个图层。
- 所有级别应该是
可访问 - 需要内存中的解决方案,即不要使用数据库表层次结构。
推荐答案
如果您只想访问数据结构的最后一级,可以使用多重映射<三<字符串,字符串,字符串>,字符串>
。 Multimap< K,V>
是来自Guava的数据结构,它基本上是一个更好的 Map< K,Collection< V>>
。 Triple< L,M, R>
是来自Apache Commons Lang3的3元素元组数据结构, Comparable
并实现等于
。
If you only ever wanted to access the last level of your data structure, you could use a Multimap<Triple<String,String,String>,String>
. Multimap<K,V>
is a data structure from Guava which basically is a nicer Map<K,Collection<V>>
. Triple<L,M,R>
is a 3-elements tuple data structure from Apache Commons Lang3 which is Comparable
and implements equals
.
您可以像这样声明您的标记树:
You could declare your tag tree like this:
Multimap<Triple<String, String, String>, String> tagTree = HashMultimap.create();
然后像这样填写:
tagTree.put(Triple.of("Java", "Active", "Tags"), "Java-OOP");
tagTree.put(Triple.of("Java", "Active", "Tags"), "Java-Variables");
或者:
tagTree.putAll(Triple.of("Java", "Active", "Tags"), Arrays.asList("Java-OOP", "Java-Variables"));
然后从中获取您的价值:
And then get your values from it like this:
Set<String> values = tagTree.get(Triple.of("Java", "Active", "Tags"));
这是另一个可能适合你的粗略解决方案可以使用1,2或3个键:
Here is another rough solution that may suit you which enables to get with 1, 2 or 3 keys:
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
public class ThreeLevelMap<K1, K2, K3, V> {
private Map<K1, Map<K2, Multimap<K3, V>>> firstLevelMap = new HashMap<>();
private Map<Pair<K1, K2>, Multimap<K3, V>> secondLevelMap = new HashMap<>();
private Multimap<Triple<K1, K2, K3>, V> thirdLevelMap = HashMultimap.create();
public void put(K1 key1, K2 key2, K3 key3, V value) {
thirdLevelMap.put(Triple.of(key1, key2, key3), value);
final Pair<K1, K2> secondLevelKey = Pair.of(key1, key2);
Multimap<K3, V> secondLevelContainer = secondLevelMap.get(secondLevelKey);
if (secondLevelContainer == null) {
secondLevelContainer = HashMultimap.create();
secondLevelMap.put(secondLevelKey, secondLevelContainer);
}
secondLevelContainer.put(key3, value);
Map<K2, Multimap<K3, V>> firstLevelContainer = firstLevelMap.get(key1);
if (firstLevelContainer == null) {
firstLevelContainer = new HashMap<>();
firstLevelMap.put(key1, firstLevelContainer);
}
firstLevelContainer.put(key2, secondLevelContainer);
}
public Collection<V> get(K1 key1, K2 key2, K3 key3) {
return thirdLevelMap.get(Triple.of(key1, key2, key3));
}
public Multimap<K3, V> get(K1 key1, K2 key2) {
return secondLevelMap.get(Pair.of(key1, key2));
}
public Map<K2, Multimap<K3, V>> get(K1 key1) {
return firstLevelMap.get(key1);
}
}
您可以这样使用它:
ThreeLevelMap<String, String, String, String> tlm = new ThreeLevelMap<>();
tlm.put("Java", "Active", "Tags", "Java-OOP");
tlm.put("Java", "Active", "Tags", "Java-Variables");
Map<String, Multimap<String, String>> firstLevelMap = tlm.get("Java");
Multimap<String, String> secondLevelMap = tlm.get("Java", "Active");
Collection<String> tags = tlm.get("Java", "Active", "Tags");
我说它很粗糙,因为:
-
get
方法返回的地图是可修改的 - 我没有实现
删除
方法 - 我没有经常测试
- the maps that the
get
methods return are modifiable - I didn't implement
remove
methods - I didn't test it a lot
这篇关于重构Map地图的Java Map的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!