如何优雅地交换 Map 中的键和值
我已经知道如何以困难的方式做到这一点并让它发挥作用 - 迭代条目并“手动”交换。但我想知道是否像许多任务一样,可以用更优雅的方式解决这个问题。
我已阅读这篇文章,不幸的是它没有优雅的特点解决方案。我也无法使用任何奇特的 Guava BiMaps 或 jdk 之外的任何东西(项目堆栈已经定义)。
我可以假设我的地图是双射的,顺便说一句:)
I already know how to do it the hard way and got it working - iterating over entries and swapping "manually". But i wonder if, like so many tasks, this one can be solved in a more elegant way.
I have read this post, unfortunately it does not feature elegant solutions. I also have no possibility to use any fancy Guava BiMaps or anything outside the jdk (project stack is already defined).
I can assume that my map is bijective, btw :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
如果您无法选择使用第三方库,我不认为以下代码如此丑陋(尽管某些脚本语言确实有优雅的方法来做到这一点):
If you don't have a choice to use a third party library, I don't consider the following code so ugly (though some scripting languages do have elegant ways of doing it):
标准 API/Java 运行时不提供双向映射,因此唯一的解决方案是迭代所有条目并手动交换它们。
您可以做的是创建一个包含两个映射的包装类,并在内部执行双重 put() 操作,以便您可以快速获得数据的两个视图。
[编辑] 另外,由于开源,您不必包含第三方库,您可以简单地将所需的类复制到您自己的项目中。
The standard API / Java runtime doesn't offer a bi-directional map, so the only solution is to iterate over all entries and swap them manually.
What you can do is create a wrapper class which contains two maps and which does a dual
put()
internally so you have fast two views on the data.[EDIT] Also, thanks to open source, you don't have to include a third party library, you can simply copy the classes you need into your own project.
映射不像列表,可以通过交换头部和尾部来反转列表。
地图中的对象具有计算的位置,并且使用值作为键和键作为值将需要重新计算存储位置,本质上是构建另一个地图。没有优雅的方法。
然而,有双向地图。这些可能适合您的需求。我会重新考虑使用第三方库。
Maps are not like lists, which can be reversed by swapping head with tail.
Objects in maps have a computed position, and using the value as key and the key as value would requiere to re-compute the storage place, essentialy building another map. There is no elegant way.
There are, however, bidirectional maps. Those may suit your needs. I'd reconsider using third-party libraries.
有些工作可以简化到一定程度,但不能再简化了。这可能就是其中之一!
如果您只想使用 Java 集合 api 来完成这项工作,那么暴力是可行的方法 - 它会很快(除非集合很大),并且将是一段明显的代码。
There are some jobs that can be simplified to a certain point and no more. This may be one of them!
If you want to do the job using Java collections apis only then brute force is the way to go - it will be quick (unless the collection is huge) and it will be an obvious piece of code.
作为回答的提示
https://stackoverflow.com/a/42091477/8594421
仅当映射不是 HashMap 并且不不包含重复值。
抛出异常
java.lang.IllegalStateException:如果值多次出现,则会出现
。解决办法:
As a hint to answer
https://stackoverflow.com/a/42091477/8594421
This only works, if the map is not a HashMap and does not contain duplicate values.
throws an exception
if there are values more than once.
The solution:
如果您有权访问 apache commons-collections,则可以使用 MapUtils.invertMap。
注意:重复值的行为未定义。
(回复此,因为这是“java invert map”的第一个谷歌结果)。
If you had access to apache commons-collections, you could have used MapUtils.invertMap.
Note: The behaviour in case of duplicated values is undefined.
(Replying to this as this is the first google result for "java invert map").
Java 流 API 提供了一组很好的 API 可以帮助您完成此任务。
如果值是唯一的,则以下内容将起作用。当我指的是值时,我指的是 Map中的 V。
如果值不唯一,则使用以下内容:
感谢 Nikita 和 FreyaZ。作为新答案发布,因为 Nikita 的答案有很多编辑队列
Java stream API provides nice set of APIs that would help you with this.
If the values are unique then the below would work. When I mean values, I mean the V in the Map<K, V>.
If the values are not unique, then use below:
Thanks Nikita and FreyaZ. Posting as new answer as there were so many edit queues for Nikita's Answer
这也适用于映射中的重复值,但不适用于
HashMap
作为值。This will work for duplicate values in the map also, but not for
HashMap
as values.无论映射中使用什么数据类型,此方法都会将键与值交换。
如果并非所有值都是唯一的(因此不能成为唯一键),则会抛出 IllegalStateException。
This method will swap keys with values, regardless of the data types used in the map.
IllegalStateException is thrown if not all values are unique (and therefore cannot become unique keys).