如何制作带有两个索引的Map?

我在java中有一个这样的Map:

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

我想通过使用index1index2作为查找来在地图中获取我的Object

如果您愿意使用第三方库,最简单的方法是使用Guava Table

它的工作原理如下:

 Table table = HashBasedTable.create(); table.put(index1, index2, obj); Object retrievedObject = table.get(index1, index2); 

您可以按照以下说明将它添加到项目中: 如何将Guava添加到Eclipse项目中


如果你不想使用番石榴,你就有一个大问题。 如果您尝试使用新的第一个键插入元素,则必须确保内部映射已存在。 这意味着,每次执行put ,都必须检索innerMap ,看它是否存在,然后创建它,如果不存在的话。 每次调用Map.put时都必须这样做。 此外,如果在内部地图上调用get时内部地图不存在,则可能会抛出NullPointerException

如果这样做,应将Map包装在外部类中以管理这些问题,或者使用Java 8的computeIfAbsent 。 但最简单的方法是使用Table如上所述。

如果您使用自己的类代替Table ,它将类似于:

 public class DoubleMap { private final Map> backingMap; public DoubleMap() { this.backingMap = new HashMap<>(); } public V get(R row, C column) { Map innerMap = backingMap.get(row); if(map == null) return null; else return innerMap.get(column); } public void put(R row, C column, V value) { Map innerMap = backingMap.get(row); if(innerMap == null) { innerMap = new HashMap(); backingMap.put(row, innerMap); } innerMap.put(column, value); } } 

你可以通过这样做来使用这个类:

 DoubleMap map = new DoubleMap(); 

请注意,此答案的function比Guava版本少得多。

Map获取价值

如果我理解你的问题,那么使用索引ab可能看起来像(使用三元或条件运算符防止null ? : :) ,

 Object obj = (map.get("a") == null) ? null : map.get("a").get("b"); 

使用通用类型

而且你可能更具体,比如

 Map> map = new HashMap<>(); Something s = (map.get("a") == null) ? null : map.get("a").get("b"); 

Map添加值

假设您要将Something value添加到map ,可以通过类似的方式完成,

 Map> map = new HashMap<>(); if (map.get("a") == null) { map.put("a", new HashMap<>()); } map.get("a").put("b", value); 

如果您不需要定期访问整个“行”,只需快速访问每个单元格,您可以使用内置的Map.Entry作为键:

 Map, Object> table = new Map<>(); table.put(new Map.SimpleEntry("index1", "index2"), "Hello world"); 

或者,如果你愿意使用第三方的东西,有几个人已经实现了Java的元组 。

如果您处于无法轻松Map.Entry第三方库的情况,但您不喜欢Map.Entry (使用key s和value s编写)的语义,则可以编写自己的Pair类有同样的效果。

根据我的理解,你可以这样做:

 Map map= new HashMap(); Map subMap = map.get("index1"); if(subMap != null) { Object obj = subMap.get("index2"); } 

最佳解决方案可能取决于该地图的使用方式:

  • 它是在有限的范围内使用,还是公共API的一部分?
  • “索引”总是String类型,还是必须是通用的?
  • 它总是两个指数,或者您以后可能需要更多指数吗?

一个实用的解决方案专注于您所描述的问题,它将引入一个可用于索引的StringPair类。 这样可以省去内部映射的2D查找(以及内部映射变空时可能的清理!),不需要任何第三方库,并且可读且高效。

 import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; public class StringPairMapTest { public static void main(String[] args) { Map map = new LinkedHashMap(); map.put(StringPair.of("A","B"), 12); map.put(StringPair.of("C","D"), 34); System.out.println(map.get(StringPair.of("A","B"))); System.out.println(map.get(StringPair.of("C","D"))); System.out.println(map.get(StringPair.of("X","Y"))); } } class StringPair { private final String s0; private final String s1; static StringPair of(String s0, String s1) { return new StringPair(s0, s1); } private StringPair(String s0, String s1) { this.s0 = s0; this.s1 = s1; } @Override public String toString() { return "("+s0+","+s1+")"; } @Override public int hashCode() { return Objects.hash(s0, s1); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; StringPair other = (StringPair) obj; return Objects.equals(s0, other.s0) && Objects.equals(s1, other.s1); } } 

当然,对于PairTuple推广是可能的,但这似乎不是你一直在寻找的……