如何转换Map映射<长 ,字符串>? (选项:使用番石榴)

发布于 2024-11-03 02:50:45 字数 400 浏览 0 评论 0原文

我有一个 Map String 键只不过是数字值,如“123”等。我正在获取数字值,因为这些值来自我的 JSF 组件中的 UI。我不想改变 UI 组件的契约。

现在我想基于上面的Map创建一个Map,我在中看到了一些transform方法Maps 类,但都专注于转换值而不是键。

有没有更好的方法将 Map 转换为 Map

I have a Map<String, String> the String key is nothing but numeric value like "123" etc. I'm getting numeric value because this values are coming from the UI in my JSF component. I don't want to change the contract of UI component.

Now I would like to create a Map<Long, String> based on the above Map, I saw some transform methods in the Maps class but all are focusing on the converting value and not key.

Is there any better way to convert Map<String, String> to Map<Long, String> ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

冷情 2024-11-10 02:50:45

@Vivin 的答案是正确的,但我认为解释为什么 Guava 没有任何方法允许您转换 Map 的键(或转换 Set > 根本)。

Guava 的所有转换和过滤方法都会产生惰性结果......函数/谓词仅在需要时才应用,因为使用对象。他们不创建副本。但正因为如此,转换很容易违反 Set 的要求。

例如,假设您有一个 Map,其中同时包含“1”和“01”作为键。它们都是不同的 String,因此 Map 可以合法地将两者包含为键。但是,如果使用 Long.valueOf(String) 转换它们,它们都会映射到值 1。它们不再是不同的键。如果您创建地图的副本并添加条目,这不会破坏任何内容,因为任何重复的键都会覆盖该键的先前条目。但是,惰性转换的 Map 无法强制执行唯一键,因此会破坏 Map 的约定。

@Vivin's answer is correct, but I think it's useful to explain why Guava doesn't have any method to allow you to transform the keys of a Map (or to transform a Set at all).

All of Guava's methods for transforming and filtering produce lazy results... the function/predicate is only applied when needed as the object is used. They don't create copies. Because of that, though, a transformation can easily break the requirements of a Set.

Let's say, for example, you have a Map<String, String> that contains both "1" and "01" as keys. They are both distinct Strings, and so the Map can legally contain both as keys. If you transform them using Long.valueOf(String), though, they both map to the value 1. They are no longer distinct keys. This isn't going to break anything if you create a copy of the map and add the entries, because any duplicate keys will overwrite the previous entry for that key. A lazily transformed Map, though, would have no way of enforcing unique keys and would therefore break the contract of a Map.

救星 2024-11-10 02:50:45

Java 8 的更新

您可以使用流来执行此操作:

Map<Long, String> newMap = oldMap.entrySet().stream()
  .collect(Collectors.toMap(e -> Long.parseLong(e.getKey()), Map.Entry::getValue));

这假设所有键都是 Long 的有效字符串表示形式。另外,变形时可能会发生碰撞;例如,"0""00" 都映射到 0L


我认为您必须迭代地图:

Map<Long, String> newMap = new HashMap<Long, String>();
for(Map.Entry<String, String> entry : map.entrySet()) {
   newMap.put(Long.parseLong(entry.getKey()), entry.getValue());
}

此代码假设您已经清理了 map 中的所有值(因此没有无效的长值)。

我希望有更好的解决方案。

编辑

我遇到了CollectionUtils#transformedCollection(Collection, Transformer) 方法看起来可能会执行您想要的操作。 从头开始​​,它只是适用于实现Collection 的类。

UPDATE for Java 8

You can use streams to do this:

Map<Long, String> newMap = oldMap.entrySet().stream()
  .collect(Collectors.toMap(e -> Long.parseLong(e.getKey()), Map.Entry::getValue));

This assumes that all keys are valid string-representations of Longs. Also, you can have collisions when transforming; for example, "0" and "00" both map to 0L.


I would think that you'd have to iterate over the map:

Map<Long, String> newMap = new HashMap<Long, String>();
for(Map.Entry<String, String> entry : map.entrySet()) {
   newMap.put(Long.parseLong(entry.getKey()), entry.getValue());
}

This code assumes that you've sanitized all the values in map (so no invalid long values).

I'm hoping there is a better solution.

EDIT

I came across the CollectionUtils#transformedCollection(Collection, Transformer) method in Commons Collection-Utils that looks like it might do what you want. Scratch that, it only works for classes that implement Collection.

尤怨 2024-11-10 02:50:45

现在,您可以使用 Java 8 流、映射、收集以更易读、更简洁的方式执行此操作。

Map<String, String> oldMap

Map<Long, String> newMap = oldMap.entrySet().stream()
  .collect(Collectors.toMap(entry -> Long.parseLong(entry.getKey()), Map.Entry::getValue));

You can now use Java 8 stream, map, collect to do this in a more readable, clean manner.

Map<String, String> oldMap

Map<Long, String> newMap = oldMap.entrySet().stream()
  .collect(Collectors.toMap(entry -> Long.parseLong(entry.getKey()), Map.Entry::getValue));
打小就很酷 2024-11-10 02:50:45

这是下面答案之一的更新版本,使生成的 Map 不可修改(不,它不使用 Guava,只是普通的 Java 8):

  import static java.util.stream.Collectors.collectingAndThen;
  import static java.util.stream.Collectors.toMap;

  ...

  newMap = oldMap.entrySet().stream().collect(collectingAndThen(
              toMap((Map.Entry<String, String> entry) -> transformKey(entry.getKey()),
                    (Map.Entry<String, String> entry) -> transformValue(entry.getValue())),
              Collections::unmodifiableMap)));

Here's an updated version of one of the answers below to make the resulting Map unmodifiable (no, it's not using Guava, just plain Java 8):

  import static java.util.stream.Collectors.collectingAndThen;
  import static java.util.stream.Collectors.toMap;

  ...

  newMap = oldMap.entrySet().stream().collect(collectingAndThen(
              toMap((Map.Entry<String, String> entry) -> transformKey(entry.getKey()),
                    (Map.Entry<String, String> entry) -> transformValue(entry.getValue())),
              Collections::unmodifiableMap)));
沙沙粒小 2024-11-10 02:50:45

简短的回答是否定的,Guava 不提供开箱即用的功能。

简单的方法如下所示。不过,也有一些警告。

    public static <K, V, L, W> Map<L, W> transformMap(Map<K, V> map, Function<K, L> keyFunction, Function<V, W> valueFunction) {
    Map<L, W> transformedMap = newHashMap();

    for (Entry<K, V> entry : map.entrySet()) {
        transformedMap.put(
                keyFunction.apply(entry.getKey()),
                valueFunction.apply(entry.getValue()));
    }

    return transformedMap;
}

public static <K, V, L> Map<L, V> transformKeys(Map<K, V> map, Function<K, L> keyFunction) {
    return transformMap(map, keyFunction, Functions.<V>identity());
}

Guava 的 Transformer 都是“惰性的”或者基于视图的。我认为要实现地图键转换器,您需要一个双向功能。我的理解是,Guava 团队正在开发一个 Converter,它可以解决这个问题。

您遇到的另一个问题是,您必须处理重复的可能性才能“防吉米”,另一个 Guava 原则。处理该问题的一种方法是返回 多重地图;另一种方法是在遇到重复项时抛出异常。我不建议隐藏问题,例如通过忽略具有重复键的后续条目,或通过使用重复键覆盖新条目。

The short answer is no, Guava does not provide this one out of the box.

The simple way would be something like below. There are some cautions, however.

    public static <K, V, L, W> Map<L, W> transformMap(Map<K, V> map, Function<K, L> keyFunction, Function<V, W> valueFunction) {
    Map<L, W> transformedMap = newHashMap();

    for (Entry<K, V> entry : map.entrySet()) {
        transformedMap.put(
                keyFunction.apply(entry.getKey()),
                valueFunction.apply(entry.getValue()));
    }

    return transformedMap;
}

public static <K, V, L> Map<L, V> transformKeys(Map<K, V> map, Function<K, L> keyFunction) {
    return transformMap(map, keyFunction, Functions.<V>identity());
}

Guava's transformers are all "lazy" or view-based. I think to implement a map key transformer, you'd want a two-way function. My understanding is that there is a Converter that is in the works by the Guava team, which would solve that problem.

The other problem you run into is that you'd have to deal with the possibility of duplicates in order to be "Jimmy-proof", another Guava principle. One way to handle that would be to return a Multimap; another would be to throw an exception when you encounter duplicates. What I would not suggest is hiding the problem e.g. by ignoring subsequent entries with duplicate keys, or by overwriting the new entry with the duplicate key.

栀梦 2024-11-10 02:50:45

使用 Java 8 和 jOOλ 进行回答

private static <K1, K2, V> Map<K2, V> mapKeys(Map<K1, V> map, Function<K1, K2> keyMapper) {
    return Seq.seq(map).map(t -> t.map1(keyMapper)).toMap(Tuple2::v1, Tuple2::v2);
}

Answer using Java 8 and jOOλ

private static <K1, K2, V> Map<K2, V> mapKeys(Map<K1, V> map, Function<K1, K2> keyMapper) {
    return Seq.seq(map).map(t -> t.map1(keyMapper)).toMap(Tuple2::v1, Tuple2::v2);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文