有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何将Map<String,String>转换为Map<Long,String>?(选项:使用番石榴)

我有一个Map<String, String>String键只不过是数字值,比如“123”等等。我得到的是数字值,因为这些值来自JSF组件中的UI。我不想更改UI组件的约定

现在我想基于上面的Map创建一个Map<Long, String>,我在Maps类中看到了一些transform方法,但是所有方法都关注转换值而不是键

有没有更好的方法将Map<String, String>转换为Map<Long, String>


共 (6) 个答案

  1. # 1 楼答案

    下面是以下答案之一的更新版本,以使生成的地图不可修改(不,它没有使用番石榴,只使用纯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)));
    
  2. # 2 楼答案

    针对Java 8的更新

    您可以使用streams来实现这一点:

    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中的所有值(因此没有无效的长值)

    我希望有更好的解决办法

    编辑

    我在Commons Collection Utils中遇到了^{}方法,它看起来可能会满足您的需求 请注意,它只适用于实现Collection的类

  3. # 3 楼答案

    @Vivin的答案是正确的,但我认为解释一下为什么番石榴没有任何方法可以让你转换Map(或者根本转换Set)的键是有用的

    番石榴的所有转换和过滤方法都会产生懒惰的结果。。。函数/谓词仅在使用对象时需要时应用。他们不会复制。不过,正因为如此,转换很容易打破Set的要求

    比如说,你有一个Map<String, String>,其中包含“1”和“01”作为键。它们都是不同的String,因此Map可以合法地包含这两个密钥。但是,如果使用Long.valueOf(String)转换它们,它们都会映射到值1。它们不再是不同的钥匙。如果创建地图副本并添加条目,这不会破坏任何东西,因为任何重复的键都会覆盖该键的上一个条目。不过,延迟转换的Map将无法强制执行唯一密钥,因此将破坏Map的契约

  4. # 4 楼答案

    现在,您可以使用Java8流、映射、收集以更可读、更干净的方式完成这项工作

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

    使用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);
    }
    
  6. # 6 楼答案

    简而言之,答案是否定的,番石榴不提供这种现成的

    简单的方法如下。然而,也有一些警告

        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());
    }
    

    番石榴的变形金刚都是“懒惰”或基于视图的。我认为要实现一个映射键转换器,你需要一个双向函数。据我所知,番石榴团队正在研发一种转换器,可以解决这个问题

    你遇到的另一个问题是,为了成为另一个番石榴原则,你必须处理重复的可能性。处理这个问题的一种方法是返回一个Multimap;另一种方法是在遇到重复项时抛出异常。我不建议隐藏问题,例如忽略具有重复密钥的后续条目,或使用重复密钥覆盖新条目