【问题标题】:Convert a set to map in java在java中将集合转换为映射
【发布时间】:2017-03-21 08:02:20
【问题描述】:

我有一套,我想把它转换成地图,以便以后在 guava 的Maps.difference() 中使用它。我只关心差异的关键。
想出了这个版本:

private <T> Map<T, T> toMap(Set<T> set) {
  return set.stream().collect(Collectors.toMap(Function.identity(), Function.identity()));
}

但是,我知道通常,一个集合有一个 map 的支持字段。这是我用来创建地图的方法:

public static <E> Set<E> newConcurrentHashSet() {
  return Collections.newSetFromMap(new ConcurrentHashMap<E, Boolean>());
}

由于我只需要密钥,我想也许我可以通过某种方式查看该字段。有什么想法吗?

【问题讨论】:

  • 为什么不使用google.github.io/guava/releases/snapshot/api/docs/com/google/…?你为什么要强制一个集合进入地图?
  • 我想知道哪些只在左边,哪些只在右边,哪些是共同的(类似于地图差异)
  • 如果您只需要密钥,为什么要转换为 Map?地图基本上是一个带有值的集合,所以你所说的没有意义。

标签: java guava


【解决方案1】:

我最终得到了一个相当简单的 Java 8 单行解决方案,如下所示:

Map<String, Foo> map = fooSet.stream().collect(Collectors.toMap(Foo::getKey, e -> e));
  • fooSet 是一组 Foo 类型的对象,即Set&lt;Foo&gt; fooSet
  • Foo 有一个名为 getKey 的 getter,它返回一个字符串

【讨论】:

    【解决方案2】:

    改进developer的回答:

    Map<String, Foo> map = fooSet.stream().collect(Collectors.toMap(Foo::getKey, Function.identity()));
    

    或者如果您静态导入Collectors.toMapFunction.identity

    Map<String, Foo> map = fooSet.stream().collect(toMap(Foo::getKey, identity()));
    

    【讨论】:

      【解决方案3】:

      您可以将Set 转换为Map(取自Set 元素的相同键和值),如下所示:

      private <T> Map<T, T> toMap(Set<T> set) {
          Map<T, T> map = new ConcurrentHashMap<>();
          set.forEach(t -> map.put(t, t));//contains same key and value pair
          return map;
      }
      

      【讨论】:

        【解决方案4】:

        来自comment

        我想知道哪些项目只在左边,哪些只在右边,哪些是共同的(类似于地图差异)

        使用removeAll() 和 [retainAll()][3]

        例子:

        Set<Integer> set1 = new HashSet<>(Arrays.asList(1,3,5,7,9));
        Set<Integer> set2 = new HashSet<>(Arrays.asList(3,4,5,6,7));
        
        Set<Integer> onlyIn1 = new HashSet<>(set1);
        onlyIn1.removeAll(set2);
        
        Set<Integer> onlyIn2 = new HashSet<>(set2);
        onlyIn2.removeAll(set1);
        
        Set<Integer> inBoth = new HashSet<>(set1);
        inBoth.retainAll(set2);
        
        System.out.println("set1: " + set1);
        System.out.println("set2: " + set2);
        System.out.println("onlyIn1: " + onlyIn1);
        System.out.println("onlyIn2: " + onlyIn2);
        System.out.println("inBoth : " + inBoth);
        

        输出

        set1: [1, 3, 5, 7, 9]
        set2: [3, 4, 5, 6, 7]
        onlyIn1: [1, 9]
        onlyIn2: [4, 6]
        inBoth : [3, 5, 7]
        

        现在,如果您想知道所有值以及它们的找到位置,您可以这样做 (Java 8):

        Set<Integer> setA = new HashSet<>(Arrays.asList(1,3,5,7,9));
        Set<Integer> setB = new HashSet<>(Arrays.asList(3,4,5,6,7));
        
        Map<Integer, String> map = new HashMap<>();
        for (Integer i : setA)
            map.put(i, "In A");
        for (Integer i : setB)
            map.compute(i, (k, v) -> (v == null ? "In B" : "In Both"));
        
        System.out.println("setA: " + setA);
        System.out.println("setB: " + setB);
        map.entrySet().stream().forEach(System.out::println);
        

        输出

        setA: [1, 3, 5, 7, 9]
        setB: [3, 4, 5, 6, 7]
        1=In A
        3=In Both
        4=In B
        5=In Both
        6=In B
        7=In Both
        9=In A
        

        【讨论】:

          【解决方案5】:

          查看类似答案here

          假设您的原始集合是一组值(原始数据中没有键!),您需要为新创建的地图指定键。 Guava 的 Maps.uniqueIndex 可能会有所帮助(请参阅 here

          否则,如果您的原始集合是您想要保留的一组键(原始数据中没有值!),您将需要为新创建的地图指定默认值或特定值。 Guava 的Maps.toMap 在这里可能会有所帮助。 (查看更多here

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-10-25
            • 2013-05-30
            • 1970-01-01
            • 1970-01-01
            • 2019-07-06
            • 2022-01-20
            • 1970-01-01
            • 2016-10-20
            相关资源
            最近更新 更多