地图也可以是集合吗?

3
我想要一个既是Map又是Collection的对象。更具体地说,我想要能够迭代Map中的条目,包括存在特定键的多个条目的情况。
我要解决的具体问题是提供一个可以在jstl中使用的对象,可以使用进行迭代,并且可以在表达式${a.b.c}中使用。在这个例子中,我希望${a.b.c}求值为 c 的第一个值(如果没有,则为空),但也能够使用<c:forEach items="${a.b.c}">迭代所有 c 并且循环体逐个查看每个 c 的值,尽管它们在Map中具有相同的键。
从方法的角度来看,这应该很简单,只需要提供一个Map实现,其中entrySet()方法返回具有相同键的多个Entries的集合。但由于这似乎违反了Map的约定,会不会以微妙而灾难性的方式破坏事情呢?还有其他人做过这样的事情吗?
(如果你猜到我试图呈现xml,那么你是正确的)
编辑
请注意,这是用于jstl,因此我提供的任何接口都必须满足两个条件:
用于[]和.运算符,它必须是Map,List,数组或JavaBeans对象(其中它不能是List或数组,因为索引不是数字)
对于forEach,它必须是数组,Collection,Iterator,Enumeration,Map或String。
因此,我想问的真正问题是,我能否只依赖于jstl调用.containsKey(),.get()和.entrySet()而不关心违反不变量,并且不在内部复制不会保留特殊迭代行为的Map吗?
4个回答

5

接近了,但那不是我需要的。我不想让 get() 方法返回所有值的列表,我想让它返回某个单一明确定义的值(即第一个值)。它似乎也不是一个 Map,所以我不能在 jstl EL 中不加修改地使用它。 - evil otto

0

我几乎不记得jstl了,但你说的听起来有点有争议:

在foreach中:

这里${a.b.c}应该指向一些值的容器,然后我们对其进行迭代。

另一方面,你说,${a.b.c}“应该评估为c的第一个值”(或null...),这是一个模棱两可的定义。

如果你觉得Multimap不是你想要的,你可以提供自己的集合实现(可能是基于Multimap的内部实现)。

只是一个想法,你总是可以将单个元素视为列表(由一个元素偶然组成)。这样你就可以解决你的歧义,我猜。

希望这可以帮助你。


是的,这个表达式是有歧义的,具体含义取决于上下文。但是我可以通过说明字符串值将完全等于第一个值来在实现中消除歧义。整个问题源于试图在一个模棱两可的情况下做到最好(即定义明确且不会出现异常;由于显而易见的原因,正确性是不可能的)。 - evil otto

0

如果一个Map中有多个相同键的条目,那么就会不可避免地破坏Map的约定。如果Multimap对您无效,则没有办法在不破坏很多东西的情况下完成此操作。

具体来说,如果您将您的怪物传递给某些指定接受Map的内容,它几乎肯定会出问题...而且听起来这正是您想要做的事情,所以是的。


它真的会吗?它不符合契约,但我能想到的唯一违反的不变量是∀x ∈ Map.entrySet x.getValue == Map.get(x.getKey),如果这个不被验证,那又有谁在乎呢? - evil otto
你会破坏 keySet().size() == entrySet().size() 的身份。但是,你已经提到的不变量实际上是我编写需要 Map 参数的代码中非常常见的假设 - 如果你打破了它,就无法知道所有可能出错的事情。 - Louis Wasserman

0
你可以使用一个以集合为值的映射表(Map),这样你便可以为相同的键设置不同的值,并且可以通过嵌套的 foreach 循环对它们进行迭代。
如果需要,你还可以很容易地编写一个现有映射实现的包装器,以便为所有值提供单个迭代器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接