简体   繁体   English

在java中将集合转换为映射

[英]Convert a set to map in java

I have a set and I want to convert it to map in order to use it later in guava's Maps.difference() .我有一套,我想将其转换为地图,以便稍后在番石榴的Maps.difference()中使用它。 I only care about the keys in the difference.我只关心差异中的关键。
Came up with this version:想出了这个版本:

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

However, I know that usually, a set has a backing field of map.但是,我知道通常,一个集合有一个 map 的支持字段。 This is the method I use to create the map:这是我用来创建地图的方法:

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

Since I only need the keys I thought maybe I can get a view of this field somehow.因为我只需要钥匙,我想也许我可以以某种方式了解这个领域。 any idea?任何想法?

I ended up with a fairly straight-forward one line solution with Java 8 as follows:我最终得到了一个相当简单的 Java 8 单行解决方案,如下所示:

Map<String, Foo> map = fooSet.stream().collect(Collectors.toMap(Foo::getKey, e -> e));
  • fooSet is a set of objects of type Foo, ie Set<Foo> fooSet fooSet 是一组 Foo 类型的对象,即Set<Foo> fooSet
  • Foo has a getter called getKey which returns a String Foo 有一个名为getKey的 getter,它返回一个字符串

You can convert a Set to a Map (same key and value taken from elements of Set ) as shown below:您可以将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;
}

Improvement of developer 's answer:改进开发人员的回答:

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

or if you statically import Collectors.toMap and Function.identity :或者如果您静态导入Collectors.toMapFunction.identity

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

From comment :来自评论

I would like to know which items only on left, which only on right, which in common (similar to map difference)我想知道哪些项目只在左边,哪些只在右边,哪些是共同点(类似于地图差异)

Use removeAll() and [ retainAll()][3] .使用removeAll()和 [ retainAll()][3]

Example:例子:

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

Output输出

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

Now, if you want to know all values and where they were found, you can do this (Java 8):现在,如果您想知道所有值以及它们的位置,您可以这样做(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);

Output输出

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

See similar answer here . 在这里看到类似的答案。

Assuming that your original set is a set of values (no keys in original data!), you will need to specify keys for the newly created map.假设您的原始集合是一组值(原始数据中没有键!),您将需要为新创建的映射指定键。 Guava's Maps.uniqueIndex might be helpful (see here ) Guava 的Maps.uniqueIndex可能会有所帮助(请参阅此处

Otherwise, if your original set is a set of keys (no values in original data!) that you want to retain, you will need to specify default or specific values for the newly created map.否则,如果您的原始集合是要保留的一组键(原始数据中没有值!),您将需要为新创建的映射指定默认值或特定值。 Guava's Maps.toMap might be helpful here. Guava 的Maps.toMap在这里可能会有所帮助。 (See more here ) 在这里查看更多)

package com.example;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {    
        Set<Foo> s = new HashSet<>();
        s.add(new Foo("cccc"));
        s.add(new Foo("aaaa"));
        s.add(new Foo("bbb"));
        Map<String, Foo> m = s.stream().collect(Collectors.toMap(Foo::getKey, Function.identity()));
        System.out.println(m);
    }
}

class Foo {
    String name;
    Foo(String name){this.name = name;}
    String getKey() {return name;}
}

Important note from the reference : 参考中的重要说明:

The returned Collector is not concurrent.返回的 Collector 不是并发的。 For parallel stream pipelines, the combiner function operates by merging the keys from one map into another, which can be an expensive operation.对于并行流管道,组合器功能通过将键从一个映射合并到另一个映射来操作,这可能是一项昂贵的操作。 If it is not required that results are inserted into the Map in encounter order, using toConcurrentMap(Function, Function) may offer better parallel performance.如果不需要将结果按遇到顺序插入 Map,使用 toConcurrentMap(Function, Function) 可能会提供更好的并行性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM